-
-
Save srdjan/1d10cbd42a2d695f696dee6b47fdc5e0 to your computer and use it in GitHub Desktop.
100+ different js counter apps... |
import { h, app } from "hyperapp" | |
app({ | |
init: 0, | |
view: state => ( | |
<main> | |
<h1>{state}</h1> | |
<button onclick={state => state - 1}>-</button> | |
<button onclick={state => state + 1}>+</button> | |
</main> | |
), | |
container: document.body | |
}) |
import { NumberValue } from 'react-values' | |
const Counter = () => ( | |
<NumberValue defaultValue={0}> | |
{({ value, increment, decrement }) => ( | |
<button onClick={() => increment()}>+1</button> | |
<span>{value}</span> | |
<button onClick={() => decrement()}>-1</button> | |
)} | |
</NumberValue> | |
) |
m.mount(document.body, { | |
count : 0, | |
view : (vnode) => m("div", | |
m("div", "Count: ", vnode.state.count), | |
m("button", { onclick : () => vnode.state.count++ }, "+"), | |
m("button", { onclick : () => vnode.state.count-- }, "-") | |
) | |
}) |
import { Provider, Subscribe } from 'react-contextual' | |
const store = { | |
count: 0, | |
up: () => state => ({ count: state.count + 1 }), | |
down: () => state => ({ count: state.count - 1 }), | |
} | |
const App = () => ( | |
<Provider {...store}> | |
<Subscribe> | |
{props => ( | |
<div> | |
<h1>{props.count}</h1> | |
<button onClick={props.up}>Up</button> | |
<button onClick={props.down}>Down</button> | |
</div> | |
)} | |
</Subscribe> | |
</Provider> | |
) |
import React from 'react' | |
export const init = count => count | |
const Action = { | |
Increment: x => x + 1, | |
Decrement: x => x - 1 | |
} | |
export const update = (action, model) => action(model) | |
export const view = (signal, model) => ( | |
<div> | |
<button onClick={signal(Action.Decrement)}>-</button> | |
<div>{model}</div> | |
<button onClick={signal(Action.Increment)}>+</button> | |
</div> | |
) | |
export default {init, update, view} |
import { observable } from 'mobx'; | |
import { observer } from 'mobx-react'; | |
import React from 'react' | |
import {render} from 'react-dom' | |
const state = { n: 0 }; | |
const incr = () => state.n++; | |
const decr = () => state.n--; | |
const view = observer(() => | |
<div> | |
<h1>{state.n}</h1> | |
<button onclick={incr}>+</button> | |
<button onclick={decr}>-</button> | |
</div>) | |
render( | |
<view />, | |
document.querySelector('#app') | |
); |
import xs from 'xstream'; | |
import Cycle from '@cycle/xstream-run'; | |
import {div, button, p, makeDOMDriver} from '@cycle/dom'; | |
function main(sources) { | |
let action$ = xs.merge( | |
sources.DOM.select('.decrement').events('click').map(ev => -1), | |
sources.DOM.select('.increment').events('click').map(ev => +1) | |
); | |
let count$ = action$.fold((x,y) => x + y, 0); | |
return { | |
DOM: count$.map(count => | |
div([ | |
button('.decrement', 'Decrement'), | |
button('.increment', 'Increment'), | |
p('Counter: ' + count) | |
]) | |
) | |
}; | |
} | |
Cycle.run(main, { | |
DOM: makeDOMDriver('#main-container') | |
}); |
import React, { Component, PropTypes } from 'react' | |
import ReactDOM from 'react-dom' | |
const increment = ({ count }) => ({ count: count + 1 }); | |
const decrement = ({ count }) => ({ count: count - 1 }); | |
class Counter extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { count: 0 }; | |
} | |
render() { | |
return ( | |
<p> | |
{this.state.count} | |
<button onClick={() => this.setState(increment)}>+</button> | |
<button onClick={() => this.setState(decrement)}>-</button> | |
</p> | |
); | |
} | |
} | |
ReactDOM.render(<Counter />, document.getElementById('root')); |
var html = require('./html') | |
var app = require('./')() | |
app.model(function (state, bus) { | |
state.count = 0 | |
bus.on('increment', function (count) { | |
state.count += count | |
bus.emit('render') | |
}) | |
}) | |
app.router([ '/', mainView ]) | |
app.mount('body') | |
function mainView (state, emit) { | |
return html` | |
<body> | |
<h1>count is ${state.count}</h1> | |
<button onclick=${onIncr}>+</button> | |
<button onclick=${onDecr}>-</button> | |
</body> | |
` | |
function onIncr() { | |
emit('increment', 1) | |
} | |
function onDecr() { | |
emit('increment', -1) | |
} | |
} |
const choo = require('../../') | |
const html = require('../../html') | |
const app = choo() | |
app.model({ | |
state: { | |
counter: 0 | |
}, | |
reducers: { | |
increment: (data, state) => ({ counter: state.counter + 1 }), | |
decrement: (data, state) => ({ counter: state.counter - 1 }) | |
} | |
}) | |
const mainView = (state, prev, send) => { | |
return html` | |
<main class="app"> | |
<button onclick=${() => send('increment')}>Increment</button> | |
<button onclick=${() => send('decrement')}>Decrement</button> | |
<p>state.counter</p> | |
</main> | |
} | |
app.router((route) => [ | |
route('/', mainView) | |
]) | |
document.body.appendChild(app.start()) |
import Html exposing (Html, button, div, text) | |
import Html.App as App | |
import Html.Events exposing (onClick) | |
main = | |
App.beginnerProgram | |
{ model = model | |
, view = view | |
, update = update | |
} | |
type alias Model = Int | |
model : Model | |
model = 0 | |
type Msg = Increment | Decrement | |
update : Msg -> Model -> Model | |
update msg model = | |
case msg of | |
Increment -> model + 1 | |
Decrement -> model - 1 | |
view : Model -> Html Msg | |
view model = | |
div [] | |
[ button [ onClick Decrement ] [ text "-" ] | |
, div [] [ text (toString model) ] | |
, button [ onClick Increment ] [ text "+" ] | |
] |
module App | |
open Elmish | |
open Elmish.React | |
open Fable.Helpers.React | |
open Fable.Helpers.React.Props | |
type Model = int | |
type Msg = Increment| Decrement | |
let init() : Model = 0 | |
let update (msg:Msg) (model:Model) = | |
match msg with | |
| Increment -> model + 1 | |
| Decrement -> model - 1 | |
let view model dispatch = | |
div [] | |
[ button [ OnClick (fun _ -> dispatch Increment) ] [ str "+" ] | |
div [] [ str (string model) ] | |
button [ OnClick (fun _ -> dispatch Decrement) ] [ str "-" ] ] | |
Program.mkSimple init update view | |
|> Program.withReact "elmish-app" | |
|> Program.withConsoleTrace | |
|> Program.run |
import { cmd } from '../src' | |
import { Html } from '../src/React' | |
import * as React from 'react' | |
export type Model = number | |
export type Flags = Model | |
export const flags: Flags = 0 | |
export function init(flags: Flags): [Model, cmd.Cmd<Msg>] { | |
return [flags, cmd.none] | |
} | |
export type Msg = | |
| { type: 'Increment' } | |
| { type: 'Decrement' } | |
export function update(msg: Msg, model: Model): [Model, cmd.Cmd<Msg>] { | |
switch (msg.type) { | |
case 'Increment' : | |
return [model + 1, cmd.none] | |
case 'Decrement' : | |
return [model - 1, cmd.none] | |
} | |
} | |
export function view(model: Model): Html<Msg> { | |
return dispatch => ( | |
<div>Count: {model} | |
<button onClick={() => dispatch({ type: 'Increment' })}>+</button> | |
<button onClick={() => dispatch({ type: 'Decrement' })}>-</button> | |
</div> | |
) | |
} |
import React, { Component, PropTypes } from 'react' | |
import ReactDOM from 'react-dom' | |
import { createStore } from 'redux' | |
class Counter extends Component { | |
static propTypes = { | |
value: PropTypes.number.isRequired, | |
onIncrement: PropTypes.func.isRequired, | |
onDecrement: PropTypes.func.isRequired | |
} | |
render() { | |
const { value, onIncrement, onDecrement } = this.props | |
return ( | |
<p> | |
<button onClick={onIncrement}>+</button> | |
<button onClick={onDecrement}>-</button> | |
</p> | |
) | |
} | |
} | |
const counter = (state = 0, action) => { | |
switch (action.type) { | |
case 'INCREMENT': | |
return state + 1 | |
case 'DECREMENT': | |
return state - 1 | |
default: | |
return state | |
} | |
} | |
const store = createStore(counter) | |
const rootEl = document.getElementById('root') | |
const render = () => ReactDOM.render( | |
<Counter | |
value={store.getState()} | |
onIncrement={() => store.dispatch({ type: 'INCREMENT' })} | |
onDecrement={() => store.dispatch({ type: 'DECREMENT' })} | |
/>, | |
rootEl | |
) | |
render() | |
store.subscribe(render) |
new Vue({ | |
data: { count: 0 }, | |
render (h) { | |
return h('p', [ | |
this.count, | |
h('button', { on: { click: () => { this.count++ }}}, '+'), | |
h('button', { on: { click: () => { this.count-- }}}, '-') | |
]) | |
} | |
}).$mount('#app') |
import {html,css,createStore,component,withProp,withStore,withStyle,withMarkup} from "compo-lib"; | |
createStore((state, action) => { | |
switch (action.type) { | |
case "ADD": return state + 1; | |
case "SUB": return state - 1; | |
default: return state; | |
} | |
}, 0); | |
component( | |
"my-counter-label", | |
withProp("value"), | |
withStyle( | |
({ value }) => css` | |
:host { | |
color: ${value < 1 ? "red" : "black"}; | |
} | |
` | |
) | |
); | |
component( | |
"my-counter", | |
withStore(({ getState, dispatch }) => ({ | |
counter: getState(), | |
add: () => dispatch({ type: "ADD" }), | |
sub: () => dispatch({ type: "SUB" }) | |
})), | |
withMarkup( | |
({ counter, add, sub }) => html` | |
<div> | |
<my-counter-label value=${counter}>${counter}</my-counter-label> | |
<button onclick=${add}>+</button> | |
<button onclick=${sub}>-</button> | |
</div> | |
` | |
) | |
); |
import Dom exposing (..) | |
import Lens exposing (Lens) | |
counter : Lens m Int -> Html m | |
counter value = | |
div [] | |
[ button [onClick (Lens.modify value ((+) -1))] [text "-"] | |
, textAs toString value | |
, button [onClick (Lens.modify value ((+) 1))] [text "+"] | |
] |
(def state (atom 0)) | |
(rum/defc view < rum/reactive [state] | |
[:div | |
[:button {:on-click #(swap! state dec)} "-"] | |
[:span (rum/react state)] | |
[:button {:on-click #(swap! state inc)} "+"]]) | |
(run/mount (view state) | |
(js/document.getElementById "app")) |
import * as R from "ramda" | |
import * as U from "karet.util" | |
import React from "karet" | |
import ReactDOM from "react-dom" | |
const Counter = ({value}) => | |
<div> | |
<div>Count: {value}</div> | |
<button onClick={() => value.modify(R.add(+1))}>+</button> | |
<button onClick={() => value.modify(R.add(-1))}>-</button> | |
</div> | |
ReactDOM.render(<Counter value={U.atom(0)}/>, document.getElementById("app")) |
data Action = Increment | Decrement | |
type State = Int | |
update :: Action -> State -> State | |
update Increment count = count + 1 | |
update Decrement count = count - 1 | |
view :: State -> Html Action | |
view count = | |
div | |
[] | |
[ button [ onClick (const Increment) ] [ text "Increment" ] | |
, span [] [ text (show count) ] | |
, button [ onClick (const Decrement) ] [ text "Decrement" ] | |
] |
<p> | |
{{ count }} | |
<button on:click="set({count: count + 1})">+</button> | |
<button on:click="set({count: count - 1})">-</button> | |
</p> | |
<script> | |
export default { | |
data() { | |
return { | |
count: 0 | |
} | |
} | |
} | |
</script> |
import * as React from 'react' | |
import * as ReactDOM from 'react-dom' | |
import { Atom, F } from '@grammarly/focal' | |
const Counter = (props: { count: Atom<number> }) => | |
<F.div> | |
You have clicked this button {props.count} time(s). | |
<button onClick={() => props.count.modify(x => x + 1)}>Click again?</button> | |
</F.div> | |
const App = (props: { state: Atom<{ count: number }> }) => | |
<div> | |
<Counter count={ props.state.lens(x => x.count)} /> | |
</div> | |
ReactDOM.render(<App state={Atom.create({ count: 0 })} />, document.getElementById('app')) |
import {Block, run} from 'cyclow' | |
const Counter = () => Block({ | |
on: { | |
'in.init': () => counter => 0, | |
'dom.increment': () => counter => counter + 1, | |
'dom.decrement': () => counter => counter - 1 | |
}, | |
view: counter => ({tag:'div#app', content: [ | |
{tag: 'div.counter', content: `${counter}`}, | |
{tag: 'div.buttons', content: [ | |
{tag: 'button', on: {click: 'decrement'}, content: '-'}, | |
{tag: 'button', on: {click: 'increment'}, content: '+'} | |
]} | |
]}) | |
}) | |
run(Counter, {target: 'app'}) |
import React from 'react' | |
import { store, view } from 'react-easy-state' | |
const counter = store({ | |
num: 0, | |
incr: () => counter.num++, | |
decr: () => counter.num-- | |
}) | |
export default view(() => <> | |
<div>Count: {value}</div> | |
<button onClick={counter.incr}>+</button> | |
<button onClick={counter.decr}>-</button> | |
</>) |
import { withState } from `recompose` | |
const enhance = withState('counter', 'setCounter', 0) | |
const Counter = enhance(({ counter, setCounter }) => | |
<div> | |
Count: {counter} | |
<button onClick={() => setCounter(n => n + 1)}>Increment</button> | |
<button onClick={() => setCounter(n => n - 1)}>Decrement</button> | |
</div> | |
) |
import React, { useState } from "react" | |
import ReactDOM from "react-dom" | |
function App() { | |
const [count, setCount] = useState(0) | |
return ( | |
<p> | |
{count} | |
<button onClick={() => setCount(count + 1)}>+</button> | |
<button onClick={() => setCount(count - 1)}>-</button> | |
</p> | |
) | |
} | |
ReactDOM.render(<App />, document.getElementById("root")) |
import { html } from 'https://unpkg.com/lit-html/lit-html.js'; | |
import { component, useState } from 'https://unpkg.com/@matthewp/haunted/haunted.js'; | |
function Counter() { | |
const [count, setCount] = useState(0); | |
return html` | |
<div id="count">${count}</div> | |
<button type="button" @click=${() => setCount(count + 1)}>Increment</button> | |
<button type="button" @click=${() => setCount(count - 1)}>Decrement</button> | |
`; | |
} | |
customElements.define('my-counter', component(Counter)); |
import { useState } from '...' | |
const App = () => | |
useState(0) | |
.map(([count, setCount]) => ( | |
<div> | |
{count} | |
<button onClick={() => setCount(count + 1)}>+</button> | |
<button onClick={() => setCount(count - 1)}>-</button> | |
</div> | |
)) | |
render(<App />, main) |
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import { Observable } from "rxjs"; | |
import { map } from 'rxjs/operators'; | |
import { observeComponent } from "./observe"; | |
function state(defaultState) { | |
return new Observable((observer) => { | |
let state; | |
function setState(newState) { | |
if (typeof newState === 'function') { | |
newState = newState(state); | |
} | |
observer.next([state = newState, setState]); | |
} | |
setState(defaultState); | |
}); | |
} | |
const App = observeComponent(() => ( | |
state(0).pipe( | |
map(([count, updateCount]) => ( | |
<div className="App"> | |
<h2> {count} </h2> | |
<button onClick={() => updateCount(c => c - 1)}>Decrement</button> | |
<button onClick={() => updateCount(c => c + 1)}>Increment</button> | |
</div> | |
)) | |
) | |
)); | |
const rootElement = document.getElementById("root"); | |
ReactDOM.render(<App />, rootElement); |
const initialState = { count: 0 }; | |
function reducer(draft, action) { | |
switch (action.type) { | |
case "increment": return void draft.count++; | |
case "decrement": return void draft.count--; | |
} | |
} | |
function Counter() { | |
const [state, dispatch] = useImmerReducer(reducer, initialState); | |
return ( | |
<> | |
Count: {state.count} | |
<button onClick={() => dispatch({ type: "increment" })}>+</button> | |
<button onClick={() => dispatch({ type: "decrement" })}>-</button> | |
</> | |
); | |
} |
import { define, render } from 'omi' | |
define('my-counter', function() { | |
const [count, setCount] = this.useData(0) | |
this.useCss(`button{ color: red; }`) | |
return ( | |
<div> | |
<button onClick={() => setCount(count - 1)}>-</button> | |
<span>{count}</span> | |
<button onClick={() => setCount(count + 1)}>+</button> | |
</div> | |
) | |
}) | |
render(<my-counter />, 'body') |
module Counter where | |
import Prelude | |
import React.Basic (Component, JSX, StateUpdate(..), capture_, createComponent, make) | |
import React.Basic.DOM as R | |
component :: Component Props | |
component = createComponent "Counter" | |
type Props = { label :: String } | |
data Action = Increment | |
counter :: Props -> JSX | |
counter = make component { initialState, update, render } | |
where | |
initialState = { counter: 0 } | |
update self = case _ of | |
Increment -> Update self.state { counter = self.state.counter + 1 } | |
render self = | |
R.button | |
{ onClick: capture_ self Increment | |
, children: [ R.text (self.props.label <> ": " <> show self.state.counter) ] | |
} |
const App = () => | |
useState(0) | |
.map(([count, setCount]) => ( | |
<div> | |
{count} | |
<button onClick={() => setCount(count + 1)}> | |
+ | |
</button> | |
</div> | |
)) | |
render(<App />, main) |
const state = 0; | |
const view = state => { | |
return `<div> | |
<h1>${state}</h1> | |
<button onclick='app.run("-1")'>-1</button> | |
<button onclick='app.run("+1")'>+1</button> | |
</div>`; | |
}; | |
const update = { | |
'+1': state => state + 1, | |
'-1': state => state - 1 | |
}; | |
app.start('my-app', state, view, update); |
import { StoreProvider, useStore } from './store' | |
const Counter = () => { | |
const [state, setState] = useStore(); | |
const increment = () => | |
setState(old => ({...old, count: old.count + 1})); | |
const decrement = () => | |
setState(old => ({...old, count: old.count - 1})); | |
return ( | |
<div> | |
<button onClick={decrement}>-</button> | |
{state.count} | |
<button onClick={increment}>+</button> | |
</div> | |
); | |
}; | |
const App = () => { | |
return ( | |
<StoreProvider initialValue={{ count: 0 }}> | |
<Counter /> | |
</StoreProvider> | |
); | |
}; |
const useIncrement = () => { | |
const [state, setState] = useStore(); | |
return () => | |
setState(old => ({ | |
...old, | |
count: old.count + 1 | |
})); | |
} | |
const useDecrement = () => { | |
const [state, setState] = useStore(); | |
return () => | |
setState(old => ({ | |
...old, | |
count: old.count + 1 | |
})); | |
} | |
const Counter = () => { | |
const [{ count }] = useStore() | |
const increment = useIncrement() | |
const decrement = useDecrement() | |
return ( | |
<div> | |
<button onClick={decrement}>-</button> | |
{count} | |
<button onClick={increment}>+</button> | |
</div> | |
); | |
}; |
import React, { useState, useContext } from "react"; | |
import ReactDOM from "react-dom"; | |
import createContainer from "constate"; | |
function useCounter() { | |
const [count, setCount] = useState(0); | |
const increment = () => setCount(count + 1); | |
const decrement = () => setCount(count - 1); | |
return { count, increment, decrement }; | |
} | |
const CounterContainer = createContainer(useCounter); | |
function ButtonIncr() { | |
const { increment } = useContext(CounterContainer.Context); | |
return <button onClick={increment}>+</button>; | |
} | |
function ButtonDecr() { | |
const { decrement } = useContext(CounterContainer.Context); | |
return <button onClick={decrement}>-</button>; | |
} | |
function Count() { | |
const { count } = useContext(CounterContainer.Context); | |
return <span>{count}</span>; | |
} | |
const Counter = () => | |
<CounterContainer.Provider> | |
<Count /> | |
<ButtonIncr /> | |
<ButtonDecr /> | |
</CounterContainer.Provider> | |
const rootElement = document.getElementById("root"); | |
ReactDOM.render(<Counter />, rootElement); |
const { useState } = React; | |
const html = htm.bind(React.createElement); | |
const App = () => { | |
const [count, setCount] = useState(0); | |
const increment = () => setCount(count+1); | |
const decrement = () => setCount(count-1); | |
return html` | |
<div class="app"> | |
<button onClick=${decrement}> - </button> | |
<strong> ${count} </strong> | |
<button onClick=${increment}> + </button> | |
</div> | |
</div> | |
`; | |
}; | |
ReactDOM.render(html`<${App} />`, document.getElementById('root')); |
const initialState = { count: 0 }; | |
function reducer(state, action) { | |
switch (action.type) { | |
case 'increment': | |
return { count: state.count + 1 }; | |
case 'decrement': | |
return { count: state.count - 1 }; | |
} | |
} | |
function Counter() { | |
const [ state, dispatch ] = useReducer(reducer, initialState); | |
const increment = () => dispatch({ type: 'increment' }); | |
const decrement = () => dispatch({ type: 'decrement' }); | |
return ( | |
<> | |
Count: {state.count} | |
<button onClick={increment}>+</button> | |
<button onClick={decrement}>-</button> | |
</> | |
); | |
} |
import { _, component, invalidate, render } from "ivi"; | |
import { h1 } from "ivi-html"; | |
const Counter = component((c) => { | |
let counter = 0; | |
const ticker = useEffect(c, (interval) => { | |
const id = setInterval(() => { | |
counter++; | |
invalidate(c); | |
}, interval); | |
return () => clearInterval(id); | |
}); | |
return (interval) => ( | |
ticker(interval), | |
div(_, _, `Counter: ${counter}`), | |
); | |
}); | |
render( | |
Counter(1000), | |
document.getElementById("app"), | |
); |
<!doctype html> | |
<html lang="en"> | |
<my-counter></my-counter> | |
<script type="module"> | |
import { html } from 'https://unpkg.com/lit-html/lit-html.js'; | |
import { component, useState } from 'https://unpkg.com/haunted/haunted.js'; | |
function Counter() { | |
const [count, setCount] = useState(0); | |
return html` | |
<div id="count">${count}</div> | |
<button type="button" @click=${() => setCount(count + 1)}>Increment</button> | |
<button type="button" @click=${() => setCount(count - 1)}>Decrement</button> | |
`; | |
} | |
customElements.define('my-counter', component(Counter)); | |
</script> |
import createStore from 'storeon' | |
import { StoreContext, connect } from 'storeon/react' | |
let increment = store => { | |
store.on('@init', () => ({ count: 0 })) | |
store.on('inc', ({ count }) => ({ count: count + 1 })) | |
} | |
const store = createStore([increment]) | |
const Counter = connect('count', React.memo( | |
({ count, dispatch }) => | |
<> | |
{count} | |
<button onClick={() => dispatch('inc')} /> | |
<button onClick={() => dispatch('dec')} /> | |
</> | |
) | |
render( | |
<StoreContext.Provider value={store}> | |
<Counter/> | |
</StoreContext.Provider>, | |
document.body | |
) |
import { Component, FastDomNode, createComponent, fdObject, fdValue } from "../../src"; | |
export function createCounter() { | |
return createComponent(Counter); | |
} | |
class Counter extends Component { | |
width = 100; | |
reactive = { | |
counter: fdValue(0), | |
} | |
get counter() { | |
return this.reactive.counter; | |
} | |
onClick = () => { | |
this.counter.value += 1; | |
} | |
template: FastDomNode = { | |
tag: "button", | |
textValue: this.counter, | |
listeners: { | |
click: this.onClick | |
} | |
} |
[@react.component] | |
let counter = () => { | |
<div> | |
{ReasonReact.string("Count: " ++ string_of_int(state.count)} | |
<> | |
<Button label="Increment" onClick={_event => state.count++)} /> | |
<Button label="Decrement" onClick={_event => state.count--} /> | |
</> | |
</div>; | |
}; |
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import { createStore, createEvent, createApi } from "effector"; | |
import { useStore } from "effector-react"; | |
const $counter = createStore(0) | |
const increment = createEvent(); | |
const decrement = createEvent(); | |
$counter.on(increment, state => state + 1) | |
$counter.on(decrement, state => state - 1) | |
function Counter () { | |
const counter = useStore($counter) | |
return ( | |
<> | |
<div>{counter}</div> | |
<button onClick={increment}>+</button> | |
<button onClick={decrement}>-</button> | |
</> | |
) | |
}; | |
ReactDOM.render(<Counter />, document.body); |
import React, { useState } from "react" | |
import { createContainer } from "unstated-next" | |
import { render } from "react-dom" | |
function useCounter() { | |
let [count, setCount] = useState(0) | |
let decrement = () => setCount(count - 1) | |
let increment = () => setCount(count + 1) | |
return { count, decrement, increment } | |
} | |
let Counter = createContainer(useCounter) | |
function CounterDisplay() { | |
let counter = Counter.useContainer() | |
return ( | |
<div> | |
<button onClick={counter.decrement}>-</button> | |
<span>{counter.count}</span> | |
<button onClick={counter.increment}>+</button> | |
</div> | |
) | |
} | |
function App() { | |
return ( | |
<Counter.Provider> | |
<CounterDisplay /> | |
<CounterDisplay /> | |
</Counter.Provider> | |
) | |
} | |
render(<App />, document.getElementById("root")) |
import { html, define } from 'hybrids'; | |
export function increaseCount(host) => host.count += 1 | |
export function decreaseCount(host) => host.count -= 1 | |
export const SimpleCounter = { | |
count: 0, | |
render: ({ count }) => html` | |
Count: ${count} | |
<button onclick="${increaseCount}"/> | |
<button onclick="${decreaseCount}"/> | |
`, | |
}; | |
define('simple-counter', SimpleCounter); |
import { html } from 'hybrids'; | |
import store, { increment, decrement } from './redux'; | |
const connect = (store, mapState) => ({ | |
get: mapState ? () => mapState(store.getState()) : () => store.getState(), | |
connect: (host, key, invalidate) => store.subscribe(invalidate), | |
}); | |
const onInc = ({ offset }) => store.dispatch(increment(offset)); | |
const onDec = ({ offset }) => store.dispatch(decrement(offset)); | |
export default { | |
count: connect(store, (state) => state.count), | |
offset: 1, | |
render: ({ count, offset }) => html` | |
<style>:host { display: block; }</style> | |
<button onclick="${onInc}">+${offset}</button> | |
<button onclick="${onDec}">-${offset}</button> | |
<p>Count: ${count}</p> | |
`, | |
}; |
import { define } from 'hybrids'; | |
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import Counter from './Counter'; | |
function reactify(fn) { | |
return (host) => { | |
const Component = fn(host); | |
return (host, target) => ReactDOM.render(Component, target); | |
} | |
} | |
const ReactCounter = { | |
count: 0, | |
render: reactify(({ count }) => | |
<Counter count={count} /> | |
), | |
}; | |
define('react-counter', ReactCounter); |
import React from "react"; | |
import { ReComponent, Update } from "react-recomponent"; | |
class Counter extends ReComponent { | |
constructor() { | |
super(); | |
this.handleClick = this.createSender("CLICK"); | |
this.state = { count: 0 }; | |
} | |
static reducer(action, state) { | |
switch (action.type) { | |
case "CLICK": | |
return Update({ count: state.count + 1 }); | |
} | |
} | |
render() { | |
return ( | |
<button onClick={this.handleClick}> | |
You’ve clicked this {this.state.count} times(s) | |
</button> | |
); | |
} | |
} |
import React from 'react'; | |
import { createGlobalState } from 'react-hooks-global-state'; | |
const initialState = { counter: 0 }; | |
const { GlobalStateProvider, useGlobalState } = createGlobalState(initialState); | |
const Counter = () => { | |
const [value, update] = useGlobalState('counter'); | |
return ( | |
<div> | |
<span>Counter: {value}</span> | |
<button onClick={() => update(v => v + 1)}>+1</button> | |
<button onClick={() => update(v => v - 1)}>-1</button> | |
</div> | |
); | |
}; | |
const App = () => ( | |
<GlobalStateProvider> | |
<Counter /> | |
<Counter /> | |
</GlobalStateProvider> | |
); |
<script type="module"> | |
import Litedom from '//unpkg.com/litedom'; | |
Litedom({ | |
el: '#counterWidget', | |
data: { | |
count: 0 | |
}, | |
up(event) { | |
this.data.count++; | |
}, | |
down(event) { | |
this.data.count--; | |
} | |
}); | |
</script> | |
<div id="counterWidget"> | |
<div>Count: {this.count}</div> | |
<button @click="down">DOWN</button> | |
<button @click="up">UP</button> | |
</div> | |
import React, { useReducer } from 'react'; | |
import ReactDOM from 'react-dom'; | |
import { Provider, useTracked } from 'react-tracked'; | |
const initialState = { | |
counter: 0 | |
}; | |
const reducer = (state, action) => { | |
switch (action.type) { | |
case 'increment': return { ...state, counter: state.counter + 1 }; | |
case 'decrement': return { ...state, counter: state.counter - 1 }; | |
default: throw new Error(`unknown action type: ${action.type}`); | |
} | |
}; | |
const useValue = () => useReducer(reducer, initialState); | |
const Counter = () => { | |
const [state, dispatch] = useTracked(); | |
return ( | |
<div> | |
<span>Count:{state.counter}</span> | |
<button type="button" onClick={() => dispatch({ type: 'increment' })}>+1</button> | |
<button type="button" onClick={() => dispatch({ type: 'decrement' })}>-1</button> | |
</div> | |
); | |
}; | |
const App = () => ( | |
<Provider useValue={useValue}> | |
<Counter /> | |
</Provider> | |
); | |
ReactDOM.render(<App />, document.getElementById('app')); |
/* eslint-env browser */ | |
import React, { useState, StrictMode } from "react"; | |
import ReactDOM from "react-dom"; | |
import { Provider, useTracked } from "react-tracked"; | |
import produce from "immer"; | |
const useValue = () => | |
useState({ | |
count: 0 | |
}); | |
const Counter = () => { | |
const [state, setState] = useTracked(); | |
const increment = () => { | |
setState( | |
produce(draft => { | |
draft.count += 1; | |
}) | |
); | |
}; | |
const decrement = () => { | |
setState( | |
produce(draft => { | |
draft.count -= 1; | |
}) | |
); | |
}; | |
return ( | |
<div> | |
<div>Count: {state.count}</div> | |
<button type="button" onClick={increment}>+</button> | |
<button type="button" onClick={decrement}>-</button> | |
</div> | |
); | |
}; | |
const App = () => ( | |
<StrictMode> | |
<Provider useValue={useValue}> | |
<Counter /> | |
</Provider> | |
</StrictMode> | |
); | |
ReactDOM.unstable_createRoot(document.getElementById("app")).render(<App />); |
import React from 'react'; | |
import { createStore } from 'redux'; | |
import { | |
Provider, | |
useDispatch, | |
useTrackedState, | |
} from 'reactive-react-redux'; | |
const initialState = { | |
count: 0 | |
}; | |
const reducer = (state = initialState, action) => { | |
switch (action.type) { | |
case 'increment': return { ...state, count: state.count + 1 }; | |
case 'decrement': return { ...state, count: state.count - 1 }; | |
default: return state; | |
} | |
}; | |
const store = createStore(reducer); | |
const Counter = () => { | |
const state = useTrackedState(); | |
const dispatch = useDispatch(); | |
return ( | |
<div> | |
<span>Count: {state.count}</span> | |
<button type="button" onClick={() => dispatch({ type: 'increment' })}>+1</button> | |
<button type="button" onClick={() => dispatch({ type: 'decrement' })}>-1</button> | |
</div> | |
); | |
}; | |
const App = () => ( | |
<Provider store={store}> | |
<Counter /> | |
</Provider> | |
); |
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import { createStore, useStore } from "react-hookstore"; | |
createStore("counter", 0); | |
export function Counter() { | |
const [state, setState] = useStore("counter"); | |
return ( | |
<div> | |
<h2>Count: {state}</h2> | |
<button type="button" onClick={() => setState(state + 1)}>Inc</button> | |
<button type="button" onClick={() => setState(state - 1)}>Dec</button> | |
</div> | |
); | |
} | |
ReactDOM.render( | |
<React.Fragment> | |
<Counter /> | |
</React.Fragment>, | |
document.querySelector("#root") | |
); |
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import {ReusableProvider, createStore} from 'reusable'; | |
import {useState} from 'react'; | |
const useCounter = createStore(() => useState(0)); | |
export function Counter() { | |
const [counter] = useCounter(); | |
return ( | |
<div> | |
{counter} | |
</div> | |
); | |
} | |
function App() { | |
return ( | |
<ReusableProvider> | |
<Counter/> | |
</ReusableProvider> | |
); | |
} | |
const rootElement = document.getElementById("root"); | |
ReactDOM.render(<App />, rootElement); |
import create from 'zustand' | |
const [useStore] = create(set=> ({ | |
count: 1, | |
inc: () => set(state => ({ count: state.count + 1 })), | |
dec: () => set(state => ({ count: state.count - 1 })) | |
})) | |
function Counter() { | |
const {count, inc, dec} = useStore() | |
return ( | |
<> | |
<h1>{count}</h1> | |
<button onClick={inc}>inc</button> | |
<button onClick={dec}>dec</button> | |
</> | |
) | |
} |
import React, { useDispatch } from 'reactn' | |
const incr = (count, action) => count + action.value | |
const decr = (count, action) => count - action.value | |
const MyComponent = () => { | |
const increment = useDispatch(incr, 'count') | |
const decrement = useDispatch(decr, 'count') | |
return ( | |
<div> | |
<button onClick={() => increment({ value: 1 })}>incr</button> | |
<button onClick={() => decrement({ value: 1 })}>decr</button> | |
</div> | |
) | |
} | |
export default MyComponent |
import haunted, { useState } from 'https://unpkg.com/haunted/core.js?module'; | |
import { html, render } from 'https://unpkg.com/lighterhtml?module'; | |
const { component } = haunted({ | |
render: (what, where) => render(where, () => what) | |
}); | |
function Counter() { | |
let [count, set] = useState(0); | |
return html` | |
<h1>Counter</h1> | |
<p>count: <strong>${count}</strong></p> | |
<button onclick=${() => set(count + 1)} type="button">Increment</button> | |
<button onclick=${() => set(count - 1)} type="button">Decrement</button> | |
`; | |
} | |
customElements.define('my-counter', component(Counter)); |
(function (angular) { | |
// service | |
var CounterService = (function () { | |
function CounterService() { | |
}; | |
CounterService.prototype.count = function (object, property, from, to, duration, effect, step, finish) { | |
var target = {}; | |
// stop previous animation | |
$(object).stop(true, true); | |
object[property] = parseFloat(from || 0); | |
target[property] = parseFloat(to || 0); | |
if (object[property] == target[property]) return; | |
$(object).animate(target, { | |
duration: duration, | |
easing: effect, | |
step: step | |
}).promise().done(function () { | |
if (angular.isFunction(finish)) finish(); | |
}); | |
}; | |
return CounterService; | |
})(); | |
// directive | |
var CounterDirective = (function () { | |
function CounterDirective(counter, timeout) { | |
this.restrict = 'EAC'; | |
this.scope = { | |
to: '=', | |
value: '=', | |
effect: '=?', | |
duration: '=?', | |
finish: '&?' | |
}; | |
$counter = counter; | |
$timeout = timeout; | |
}; | |
CounterDirective.prototype.$inject = ['$counter', '$timeout']; | |
CounterDirective.prototype.link = function ($scope, $element, $attrs, $controller) { | |
var defaults = { | |
effect: 'linear', | |
duration: 1000 | |
}; | |
if (!angular.isDefined($scope.to)) | |
throw new 'Angular Counter: attribute `to` is undefined'; | |
angular.forEach(defaults, function (value, key) { | |
if (!angular.isDefined($scope[key])) $scope[key] = defaults[key]; | |
}); | |
$scope.step = function (value) { | |
$timeout(function () { | |
$scope.$apply(function () { | |
$scope.value = value; | |
}); | |
}); | |
}; | |
$scope.$watch('to', function () { | |
$counter.count($scope, 'value', $scope.value, $scope.to, $scope.duration, $scope.effect, $scope.step, $scope.finish); | |
}); | |
}; | |
return CounterDirective; | |
})(); | |
angular | |
.module('counter', []) | |
.service('$counter', function () { | |
return new CounterService(); | |
}) | |
.directive('counter', ['$counter', '$timeout', function ($counter, $timeout) { | |
return new CounterDirective($counter, $timeout); | |
}]); |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>Document</title> | |
</head> | |
<body> | |
<script type="module"> | |
import { h, app } from "https://unpkg.com/hyperapp" | |
app({ | |
init: 0, | |
view: state => | |
h("div", {}, [ | |
h("h1", {}, state), | |
h("button", { onClick: state => state - 1 }, "-"), | |
h("button", { onClick: state => state + 1 }, "+") | |
]), | |
node: document.getElementById("app") | |
}) | |
</script> | |
<div class="app"></div> | |
</body> | |
</html> |
counter id = component \on -> do | |
count <- accum (+) 0 on.change | |
( H.div {} ( | |
H.text "Counter " </> | |
H.span {} (H.textB $ map show count) </> | |
H.button {} (H.text "+" ) `use` (\o -> { change: o.click $> 1 }) </> | |
H.button {} (H.text "-" ) `use` (\o -> { change: o.click $> -1 }) | |
) | |
) `output` {} | |
main = runComponent "#mount" (counter 0) |
import React from 'react' | |
import { useBistate, useMutate } from 'bistate/react' | |
export default function Counter() { | |
let state = useBistate({ count: 0 }) | |
let incre = useMutate(() => { | |
state.count += 1 | |
}) | |
let decre = useMutate(() => { | |
state.count -= 1 | |
}) | |
return ( | |
<div> | |
<button onClick={incre}>+1</button> | |
{state.count} | |
<button onClick={decre}>-1</button> | |
</div> | |
) | |
} |
import * as React from 'react' | |
import * as ReactDOM from 'react-dom' | |
import { html, platform, state } from 'effe-ts' | |
type Action = { type: 'Increase' } | { type: 'Decrease' } | |
type Model = number | |
const init: state.State<Model> = state.of(0) | |
function update(action: Action, model: Model): state.State<Model> { | |
switch (action.type) { | |
case 'Increase': | |
return state.of(model + 1) | |
case 'Decrease': | |
return state.of(model - 1) | |
} | |
} | |
const view = (model: Model) => (dispatch: platform.Dispatch<Action>) => ( | |
<> | |
<span>Counter: {model}</span> | |
<button onClick={() => dispatch({ type: 'Increase' })}>+</button> | |
<button onClick={() => dispatch({ type: 'Decrease' })}>-</button> | |
</> | |
) | |
const app = html.program(init, update, view) | |
html.run(app, dom => ReactDOM.render(dom, document.getElementById('app')!), {}) |
import { render } from "preact"; | |
import flowponent from "flowponent"; | |
const App = flowponent(function*() { | |
let count = 0; | |
for (;;) { | |
count += yield step => ( | |
<div> | |
<div>current value: {count}</div> | |
<button onClick={() => step(1)}>+1</button> | |
<button onClick={() => step(-1)}>-1</button> | |
</div> | |
); | |
} | |
}); | |
render(<App />, document.getElementById("root")); |
const { X, x } = xreact | |
function xmount(component, dom) { ReactDOM.render(React.createFactory(X)({}, component), dom) } | |
const CounterView = ({actions, count}) => ( | |
<div> | |
<button onClick={actions.dec}>-</button> | |
<span>{count}</span> | |
<button onClick={actions.inc}>+</button> | |
</div> | |
) | |
CounterView.defaultProps = {count: 0} | |
const plan = (intent$) => { | |
return { | |
update$: intent$.map(intent => { | |
switch (intent.type) { | |
case 'inc': | |
return state => ({ count: state.count + 1 }); | |
case 'dec': | |
return state => ({ count: state.count - 1 }); | |
default: | |
return _ => _; | |
} | |
}), | |
actions: { | |
inc: () => ({ type: 'inc' }), | |
dec: () => ({ type: 'dec' }) | |
} | |
} | |
} | |
const Counter = x(plan)(CounterView); | |
xmount(<Counter/>, | |
document.getElementById('app') | |
); |
const { X, x } = xreact | |
function xmount(component, dom) { ReactDOM.render(React.createFactory(X)({}, component), dom) } | |
// Intent union type | |
interface Inc { | |
kind: 'inc' | |
} | |
interface Dec { | |
kind: 'dec' | |
} | |
type Intent = Inc | Dec | |
// State | |
interface CounterProps { | |
count: number | |
actions: Actions<Intent> | |
} | |
const CounterView: React.SFC<CounterProps> = ({actions, count}) => ( | |
<div> | |
<button onClick={actions.dec}>-</button> | |
<span>{count}</span> | |
<button onClick={actions.inc}>+</button> | |
</div> | |
) | |
CounterView.defaultProps = {count: 0} | |
const plan = (intent$) => { | |
return { | |
update$: intent$.map(intent => { | |
// now the switch is Type Safe | |
switch (intent.kind) { | |
case 'inc': | |
return state => ({ count: state.count + 1 }); | |
case 'dec': | |
return state => ({ count: state.count - 1 }); | |
default: | |
return _ => _; | |
} | |
}), | |
actions: { | |
inc: () => ({ kind: 'inc' } as Inc), | |
dec: () => ({ kind: 'dec' } as Dec) | |
} | |
} | |
} | |
const Counter = x(plan)(CounterView); | |
xmount(<Counter/>, | |
document.getElementById('app') | |
); |
import {render, html} from 'https://unpkg.com/uhtml?module'; | |
import {define, useState} from 'https://unpkg.com/hooked-elements?module'; | |
define('my-counter', element => { | |
const [count, update] = useState(0); | |
const {value, dec, inc} = render(element, html` | |
<button class="large btn" name="dec">-</button> | |
<span class="large value" name="value"></span> | |
<button class="large btn" name="inc">+</button> | |
`); | |
value.textContent = count; | |
dec.onclick = () => update(count - 1); | |
inc.onclick = () => update(count + 1); | |
}); |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Counter</title> | |
</head> | |
<body> | |
<script src="https://unpkg.com/apprun/dist/apprun-html.js"></script> | |
<script> | |
const state = 0; | |
const view = state => { | |
return `<div> | |
<h1>${state}</h1> | |
<button onclick='app.run("-1")'>-1</button> | |
<button onclick='app.run("+1")'>+1</button> | |
</div>`; | |
}; | |
const update = { | |
'+1': state => state + 1, | |
'-1': state => state - 1 | |
}; | |
app.start(document.body, state, view, update); | |
</script> | |
</body> | |
</html> |
import React, { useDispatch } from 'reactn'; // <-- reactn | |
const incrementReducer = (global, dispatch, action) => ({ | |
count: global.count + action.amount, | |
}); | |
const decrementReducer = (global, dispatch, action) => ({ | |
count: global.count - action.amount, | |
}); | |
const MyComponent = () => { | |
const increment = useDispatch(incrementReducer); | |
const decrement = useDispatch(decrementReducer); | |
return ( | |
<div> | |
<button onClick={() => increment({ amount: 1 })}>Add 1</button> | |
<button onClick={() => increment({ amount: 3 })}>Add 3</button> | |
<button onClick={() => decrement({ amount: 5 })}>Subtract 5</button> | |
</div> | |
); | |
}; | |
export default MyComponent; |
import React from "react"; | |
import {createGlobalState} from 'react-use' | |
const useGlobalValue = createGlobalState(0); | |
const CompA = () => { | |
const [value, setValue] = useGlobalValue(); | |
return <button onClick={() => setValue(value + 1)}>+</button>; | |
}; | |
const CompB = () => { | |
const [value, setValue] = useGlobalValue(); | |
return <button onClick={() => setValue(value - 1)}>-</button>; | |
}; | |
export default function App() { | |
const [value] = useGlobalValue(); | |
return ( | |
<div> | |
<p>{value}</p> | |
<CompA /> | |
<CompB /> | |
</div> | |
); | |
} |
import { h, render, useState } from 'fre' | |
function App() { | |
const [count, setCount] = useState(0) | |
return ( | |
<div> | |
<h1>{count}</h1> | |
<button onClick={() => setCount(count + 1)}>+</button> | |
<button onClick={() => setCount(count + -)}>-</button> | |
</div> | |
) | |
} | |
render(<App />, document.getElementById('root')) |
import ReactDOM from "react" | |
import Concur from "concur" | |
const stateLoop = async function*(initState, component) { | |
let state = initState | |
while(true) { | |
state = yield* component(state) | |
} | |
} | |
const Counter = stateLoop(0, (count) => | |
<div> | |
<div>The current count is {count}</div> | |
<div> | |
<button onClick={mapProp(() => count+1)}>Increment</button> | |
<button onClick={mapProp(() => count-1)}>Decrement</button> | |
<button onClick={mapProp(() => 0)}>Reset</button> | |
</div> | |
</div> | |
) | |
ReactDOM.render(<Concur><Counter/></Concur>, document.getElementById('root')); |
import {neverland as $, render, html, useState} from 'neverland'; | |
const Counter = $((initialState) => { | |
const [count, setCount] = useState(initialState); | |
return html` | |
Count: ${count} | |
<button onclick=${() => setCount(count + 1)}>Increment</button> | |
<button onclick=${() => setCount(count - 1)}>Decrement</button> | |
}); | |
render(document.body, html` | |
<div> | |
${Counter(0)} | |
</div> | |
`); |
import { component, html, prop, useObservable } from 'js-elements' | |
component('simple-counter', { | |
props: { | |
label: prop.str.opt('Counter'), | |
initialCount: prop.num.opt(0) | |
} | |
}, props => { | |
const | |
state = useObservable({ count: props.initialCount }), | |
onIncrement = () => { ++state.count }, | |
onDecrement = () => { --state.count } | |
return () => html` | |
<div> | |
<label>${props.label}: </label> | |
<button @click=${onDecrement}>-</button> | |
<span> ${state.count} </span> | |
<button @click=${onIncrement}>+</button> | |
<div> | |
` | |
}) | |
document.getElementById('app').appendChild( | |
document.createElement('simple-counter')) |
import { h, component, render, useCallback, useState } from 'js-surface/react' | |
const Counter = component({ | |
name: 'Counter', | |
validate: true, | |
main({ initialValue = 0, label = 'Counter' }) { | |
const | |
[count, setCount] = useState(initialValue), | |
onIncrement = useCallback(() => setCount(it => it + 1), []) | |
return ( | |
<div> | |
<label>{label}</label> | |
<button onClick={onIncrement}>{count}</button> | |
</div> | |
) | |
} | |
}) | |
render(<Counter/>, 'app') |
class MyCounter extends HTMLElement { | |
constructor() { | |
super(); | |
this.count = 0; | |
const style = ` | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
`; | |
const html = ` | |
<button id="dec">-</button> | |
<span>${this.count}</span> | |
<button id="inc">+</button> | |
`; | |
this.attachShadow({ mode: 'open' }); | |
this.shadowRoot.innerHTML = ` | |
<style> | |
${style} | |
</style> | |
${html} | |
`; | |
this.buttonInc = this.shadowRoot.getElementById('inc'); | |
this.buttonDec = this.shadowRoot.getElementById('dec'); | |
this.spanValue = this.shadowRoot.querySelector('span'); | |
this.inc = this.inc.bind(this); | |
this.dec = this.dec.bind(this); | |
} | |
inc() { | |
this.count++; | |
this.update(); | |
} | |
dec() { | |
this.count--; | |
this.update(); | |
} | |
update() { | |
this.spanValue.innerText = this.count; | |
} | |
connectedCallback() { | |
this.buttonInc.addEventListener('click', this.inc); | |
this.buttonDec.addEventListener('click', this.dec); | |
} | |
disconnectedCallback() { | |
this.buttonInc.removeEventListener('click', this.inc); | |
this.buttonDec.removeEventListener('click', this.dec); | |
} | |
} | |
customElements.define('my-counter', MyCounter); |
import { html, render } from 'lighterhtml'; | |
class MyCounter extends HTMLElement { | |
constructor() { | |
super(); | |
this.count = 0; | |
this.attachShadow({ mode: 'open' }); | |
this.update(); | |
} | |
inc = () => { | |
this.count++; | |
this.update(); | |
}; | |
dec = () => { | |
this.count--; | |
this.update(); | |
}; | |
style() { | |
return ` | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
`; | |
} | |
template() { | |
return html` | |
<style> | |
${this.style()} | |
</style> | |
<button onclick="${this.dec}">-</button> | |
<span>${this.count}</span> | |
<button onclick="${this.inc}">+</button> | |
`; | |
} | |
update() { | |
render(this.shadowRoot, this.template()); | |
} | |
} | |
customElements.define('my-counter', MyCounter); |
import HyperHTMLElement from "hyperhtml-element"; | |
class MyCounter extends HyperHTMLElement { | |
constructor() { | |
super(); | |
this.attachShadow({ mode: "open" }); | |
} | |
created() { | |
this.count = 0; | |
this.render(); | |
} | |
inc = () => { | |
this.count++; | |
this.render(); | |
}; | |
dec = () => { | |
this.count--; | |
this.render(); | |
}; | |
render() { | |
return this.html` | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> | |
<button onclick=${this.dec}>-</button> | |
<span>${this.count}</span> | |
<button onclick=${this.inc}>+</button> | |
`; | |
} | |
} | |
MyCounter.define("my-counter"); |
import { ComponentMixin } from "@neow/core"; | |
class MyComponent extends ComponentMixin(HTMLElement) { | |
static template = ` | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> | |
<button onclick="{{this.dec()}}">-</button> | |
<span>{{this.counter}}</span> | |
<button onclick="{{this.inc()}}">+</button> | |
`; | |
counter = 0; | |
inc() { | |
this.counter++; | |
} | |
dec() { | |
this.counter--; | |
} | |
} | |
customElements.define("my-counter", MyComponent); |
import { define, WeElement, html } from "omi"; | |
class MyCounter extends WeElement { | |
static get propTypes() { | |
return { | |
count: Number | |
}; | |
} | |
static get defaultProps() { | |
return { count: 0 }; | |
} | |
install() { | |
this.data = { count: this.props.count }; | |
} | |
static get css() { | |
return ` | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
`; | |
} | |
inc = () => { | |
this.data.count++; | |
this.update(); | |
}; | |
dec = () => { | |
this.data.count--; | |
this.update(); | |
}; | |
render(props) { | |
return html` | |
<button onclick="${this.dec}">-</button> | |
<span>${this.data.count}</span> | |
<button onclick="${this.inc}">+</button> | |
`; | |
} | |
} | |
define("my-counter", MyCounter); |
import Element from "@skatejs/element"; | |
import { render, html } from "lit-html"; | |
class MyCounterElement extends Element { | |
static get props() { | |
return { | |
count: Number | |
}; | |
} | |
inc = () => { | |
this.count++; | |
}; | |
dec = () => { | |
this.count--; | |
}; | |
render() { | |
const style = ` | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
}`; | |
return html` | |
<style> | |
${style} | |
</style> | |
<button @click="${this.dec}"> | |
- | |
</button> | |
<span>${this.count}</span> | |
<button @click="${this.inc}"> | |
+ | |
</button> | |
`; | |
} | |
renderer() { | |
return render(this.render(), this.renderRoot); | |
} | |
} | |
customElements.define("my-counter", MyCounterElement); |
import Element, { h } from "@skatejs/element-preact"; | |
class MyCounterElement extends Element { | |
static get props() { | |
return { | |
count: Number | |
}; | |
} | |
inc = () => { | |
this.count++; | |
}; | |
dec = () => { | |
this.count--; | |
}; | |
render() { | |
const style = `host * { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
}`; | |
return ( | |
<host> | |
<style>{style}</style> | |
<button onclick={this.dec}>-</button> | |
<span>{this.count}</span> | |
<button onclick={this.inc}>+</button> | |
</host> | |
); | |
} | |
} | |
customElements.define("my-counter", MyCounterElement); |
import { Slim } from "slim-js/Slim.js"; | |
import { tag, template, useShadow } from "slim-js/Decorators"; | |
@tag("my-counter") | |
@useShadow(true) | |
@template(` | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style > | |
<button click="dec">-</button> | |
<span>{{parseCount(count)}}</span> | |
<button click="inc">+</button> | |
`) | |
class MyCounter extends Slim { | |
constructor() { | |
super(); | |
this.count = 0; | |
} | |
parseCount(num) { | |
return String(num); | |
} | |
inc() { | |
this.count++; | |
} | |
dec() { | |
this.count--; | |
} | |
} |
import { h, customElement, useProp } from "atomico"; | |
function MyCounter() { | |
let [count, setCount] = useProp("count"); | |
const style = ` | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
}`; | |
return ( | |
<host shadowDom> | |
<style>{style}</style> | |
<button onclick={() => setCount(count - 1)}>-</button> | |
<span>{count}</span> | |
<button onclick={() => setCount(count + 1)}>+</button> | |
</host> | |
); | |
} | |
MyCounter.props = { | |
count: { | |
type: Number, | |
reflect: true, | |
value: 0 | |
} | |
}; | |
customElements.define("my-counter", customElement(MyCounter)); |
import { define } from "heresy"; | |
define("MyCounter", { | |
style: MyCounter => ` | |
${MyCounter} * { | |
font-size: 200%; | |
} | |
${MyCounter} span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
${MyCounter} button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
`, | |
render({ useState }) { | |
const [count, update] = useState(0); | |
this.html` | |
<button onclick="${() => update(count - 1)}">-</button> | |
<span>${count}</span> | |
<button onclick="${() => update(count + 1)}">+</button> | |
`; | |
} | |
}); |
import Litedom from "litedom"; | |
Litedom({ | |
tagName: "my-counter", | |
shadowDOM: true, | |
template: ` | |
<button @click="dec">-</button> | |
<span>{this.count}</span> | |
<button @click="inc">+</button> | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> | |
`, | |
data: { | |
count: 0 | |
}, | |
dec() { | |
this.data.count--; | |
}, | |
inc() { | |
this.data.count++; | |
} | |
}); |
import { component } from "ottavino"; | |
component({ | |
tag: "my-counter", | |
shadow: true, | |
template: ` | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> | |
<button onclick="{{this.decrease()}}">-</button> | |
<span>{{this.count}}</span> | |
<button onclick="{{this.increase()}}" >+</button> | |
`, | |
properties: { | |
count: 0 | |
}, | |
this: { | |
increase: function() { | |
this.count++; | |
}, | |
decrease: function() { | |
this.count--; | |
} | |
} | |
}); |
import { LightningElement, api, buildCustomElementConstructor } from "lwc"; | |
export default class MyCounter extends LightningElement { | |
count = 0; | |
inc() { | |
this.count++; | |
} | |
dec() { | |
this.count--; | |
} | |
} | |
customElements.define("my-counter", buildCustomElementConstructor(MyCounter)); |
import { h, Component, State, Host } from "@stencil/core"; | |
@Component({ | |
tag: "my-counter", | |
styleUrl: "index.css", | |
shadow: true | |
}) | |
export class MyCounter { | |
@State() count: number = 0; | |
inc() { | |
this.count++; | |
} | |
dec() { | |
this.count--; | |
} | |
render() { | |
return ( | |
<Host> | |
<button onClick={this.dec.bind(this)}>-</button> | |
<span>{this.count}</span> | |
<button onClick={this.inc.bind(this)}>+</button> | |
</Host> | |
); | |
} | |
} |
import { createCustomElement } from "@wcd/preact-custom-element"; | |
import { Component, html } from "htm/preact"; | |
import "preact"; | |
class MyCounter extends Component { | |
state = { | |
count: 0 | |
}; | |
inc = () => { | |
this.setState(prev => ({ count: prev.count + 1 })); | |
}; | |
dec = () => { | |
this.setState(prev => ({ count: prev.count - 1 })); | |
}; | |
render(props, state) { | |
return html` | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> | |
<button onClick=${this.dec}> | |
- | |
</button> | |
<span>${state.count}</span> | |
<button onClick=${this.inc}> | |
+ | |
</button> | |
`; | |
} | |
} | |
customElements.define("my-counter", createCustomElement(MyCounter, ["count"])); |
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import reactToWebComponent from "react-to-webcomponent"; | |
interface State { | |
count: number; | |
} | |
interface Props {} | |
export default class MyCounter extends React.Component<Props, State> { | |
constructor(props) { | |
super(props); | |
this.state = { | |
count: 0 | |
}; | |
} | |
render() { | |
const styles = `.my-counter * { | |
font-size: 200%; | |
} | |
.my-counter span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
.my-counter button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
}`; | |
return ( | |
<div className="my-counter"> | |
<style>{styles}</style> | |
<button onClick={() => this.setState({ count: this.state.count - 1 })}> | |
- | |
</button> | |
<span>{this.state.count}</span> | |
<button onClick={() => this.setState({ count: this.state.count + 1 })}> | |
+ | |
</button> | |
</div> | |
); | |
} | |
} | |
customElements.define( | |
"my-counter", | |
reactToWebComponent(MyCounter, React, ReactDOM) | |
); |
import React, { useState } from "react"; | |
import ReactDOM from "react-dom"; | |
import reactToWebComponent from "react-to-webcomponent"; | |
export default function MyCounter() { | |
const [count, setCount] = useState(0); | |
const styles = ` | |
.my-counter * { | |
font-size: 200%; | |
} | |
.my-counter span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
.my-counter button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
}`; | |
return ( | |
<div className="my-counter"> | |
<style>{styles}</style> | |
<button onClick={() => setCount(count - 1)}>-</button> | |
<span>{count}</span> | |
<button onClick={() => setCount(count + 1)}>+</button> | |
</div> | |
); | |
} | |
customElements.define( | |
"my-counter", | |
reactToWebComponent(MyCounter, React, ReactDOM) | |
); |
<my-component> | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> | |
<button onclick={dec}> | |
- | |
</button> | |
<span>{state.count}</span> | |
<button onclick={inc}> | |
+ | |
</button> | |
<script> | |
export default { | |
onBeforeMount(props, state) { | |
this.state = { | |
count: 0 | |
} | |
}, | |
inc() { | |
this.update({ | |
count: this.state.count+1 | |
}) | |
}, | |
dec() { | |
this.update({ | |
count: this.state.count-1 | |
}) | |
}, | |
} | |
</script> | |
</my-component> |
<svelte:options tag="my-counter" /> | |
<script> | |
let count = 0; | |
function inc() { | |
count++; | |
} | |
function dec() { | |
count--; | |
} | |
</script> | |
<style> | |
* { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> | |
<button on:click={dec}> | |
- | |
</button> | |
<span>{count}</span> | |
<button on:click={inc}> | |
+ | |
</button> |
<template> | |
<div> | |
<button @click="this.dec">-</button> | |
<span>{{count}}</span> | |
<button @click="this.inc">+</button> | |
</div> | |
</template> | |
<script> | |
export default { | |
tag: 'my-counter', | |
name: 'MyCounter', | |
data() { | |
return { count: 0 } | |
}, | |
methods: { | |
inc: function() { | |
this.count++; | |
}, | |
dec: function() { | |
this.count--; | |
} | |
} | |
}; | |
</script> | |
<style scoped> | |
span, | |
button { | |
font-size: 200%; | |
} | |
span { | |
width: 4rem; | |
display: inline-block; | |
text-align: center; | |
} | |
button { | |
width: 64px; | |
height: 64px; | |
border: none; | |
border-radius: 10px; | |
background-color: seagreen; | |
color: white; | |
} | |
</style> |
import { render } from "preact"; | |
import flowponent from "flowponent"; | |
const App = flowponent(function*() { | |
let count = 0; | |
for (;;) { | |
count += yield resolve => ( | |
<div> | |
<div>current value: {count}</div> | |
<button onClick={() => resolve(1)}>+1</button> | |
<button onClick={() => resolve(-1)}>-1</button> | |
</div> | |
); | |
} | |
}); | |
render(<App />, document.getElementById("root")); |
import { useStoreon } from 'storeon-solidjs' | |
let counter = store => { | |
store.on('@init', () => ({ count: 0 })) | |
store.on('inc', ({ count }) => ({ count: count + 1 })) | |
store.on('dec', ({ count }) => ({ count: count - 1 })) | |
} | |
export default function Counter() { | |
const [state, dispatch] = useStoreon() | |
return ( | |
<div> | |
{state.count} | |
<button onClick={() => dispatch('inc')}>inc</button> | |
<button onClick={() => dispatch('dec')}>dec</button> | |
</div> | |
) | |
} |
module Examples.NoEffects.Counter.Main where | |
import Prelude | |
import Effect (Effect) | |
import Flame (QuerySelector(..), Html) | |
import Flame.Application.NoEffects as FAN | |
import Flame.HTML.Element as HE | |
import Flame.HTML.Attribute as HA | |
type Model = Int | |
data Message = Increment | Decrement | |
init :: Model | |
init = 0 | |
update :: Model -> Message -> Model | |
update model = case _ of | |
Increment -> model + 1 | |
Decrement -> model - 1 | |
view :: Model -> Html Message | |
view model = HE.main "main" [ | |
HE.button [HA.onClick Decrement] "-", | |
HE.text $ show model, | |
HE.button [HA.onClick Increment] "+" | |
] | |
main :: Effect Unit | |
main = FAN.mount_ (QuerySelector "main") { | |
init, | |
update, | |
view | |
} |
import { define } from 'uce'; | |
import { render, html } from 'uhtml'; | |
define("my-counter", { | |
init() { | |
this.count = 0; | |
this.dec = () => { | |
this.count--; | |
this.render(); | |
}; | |
this.inc = () => { | |
this.count++; | |
this.render(); | |
}; | |
this.render(); | |
}, | |
render() { | |
this.html` | |
<button onclick="${this.dec}">-</button> | |
<span>${this.count}</span> | |
<button onclick="${this.inc}">+</button> | |
`; | |
} | |
}); | |
addEventListener( | |
'DOMContentLoaded', | |
() => { | |
// populate the body | |
render(document.body, html` | |
<my-counter /> | |
<footer></footer> | |
`); | |
// fetch project details and populate the footer | |
fetch('package.json') | |
.then(_ => _.json()) | |
.then(({description, version}) => { | |
render(document.querySelector('footer'), html` | |
${description} v${version} | |
`); | |
}); | |
}, | |
{once: true} | |
); |
import React from "react"; | |
import { StateLake } from "statelake"; | |
const store = new StateLake({ count: ""}); | |
export default function App() { | |
const [count, setCount] = store.useState("count")(); | |
return ( | |
<div className="App"> | |
<button onClick={() => setCount(count + 1)}>+</button> | |
<button onClick={() => setCount(count - 1)}>-</button> | |
<div>{count}</div> | |
</div> | |
); | |
} |
open Feliz | |
open Feliz.UseElmish | |
open Elmish | |
type Msg = | |
| Increment | |
| Decrement | |
type State = { Count : int } | |
let init() = { Count = 0 }, Cmd.none | |
let update msg state = | |
match msg with | |
| Increment -> { state with Count = state.Count + 1 }, Cmd.none | |
| Decrement -> { state with Count = state.Count - 1 }, Cmd.none | |
let counter = React.functionComponent(fun () -> | |
let state, dispatch = React.useElmish(init, update, [| |]) | |
Html.div [ | |
Html.h1 state.Count | |
Html.button [ | |
prop.text "Increment" | |
prop.onClick (fun _ -> dispatch Increment) | |
] | |
Html.button [ | |
prop.text "Decrement" | |
prop.onClick (fun _ -> dispatch Decrement) | |
] | |
] | |
) |
import { wired, on, component } from "capsid"; | |
@component("counter") | |
export class Counter { | |
count: number = 0; | |
@wired(".label") | |
label: HTMLElement; | |
__mount__() { | |
this.update(); | |
} | |
@on.click.at(".plus") | |
plus() { | |
this.count++; | |
this.update(); | |
} | |
@on.click.at(".minus") | |
minus() { | |
this.count--; | |
this.update(); | |
} | |
/** Updates the label. */ | |
update() { | |
this.label.textContent = `${this.count}`; | |
} | |
} |
module Main where | |
import Prelude | |
import Effect (Effect) | |
import Concur.Core (Widget) | |
import Concur.React (HTML) | |
import Concur.React.DOM as D | |
import Concur.React.Props as P | |
import Concur.React.Run (runWidgetInDom) | |
counterWidget :: forall a. Int -> Widget HTML a | |
counterWidget count = do | |
n <- D.div' | |
[ D.p' [D.text ("State: " <> show count)] | |
, D.button [P.onClick] [D.text "Increment"] $> count+1 | |
, D.button [P.onClick] [D.text "Decrement"] $> count-1 | |
] | |
counterWidget n | |
main :: Effect Unit | |
main = runWidgetInDom "main" (counterWidget 0) |
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import { Provider, createAtom, useAtom } from 'use-atom'; | |
const countAtom = createAtom({ default: 0 }); | |
const Counter = () => { | |
const [count, setCount] = useAtom(countAtom); | |
return ( | |
<div> | |
<span>Count: {count}</span> | |
<button type="button" onClick={() => setCount(count + 1)}>+1</button> | |
<button type="button" onClick={() => setCount((c) => c - 1)}>-1</button> | |
</div> | |
); | |
}; | |
const App = () => ( | |
<Provider> | |
<h1>Counter</h1> | |
<Counter /> | |
</Provider> | |
); |
import { createState } from "solid-js"; | |
const Counter = () => { | |
const [state, setState] = createState({ counter: 0 }); | |
return <div> | |
{state.counter} | |
<button type="button" onClick={() => setState({ counter: state.counter + 1 }}>+1</button> | |
<button type="button" onClick={() => setState({ counter: state.counter - 1 }}>-1</button> | |
</div>; | |
}; | |
render(() => createComponent(Counter, document.getElementById("app")); |
import React from 'react'; | |
import { hawk, hawkeye, useHawkState, useHawkSetState } from 'react-hawk'; | |
const counterState = hawk({ | |
key: 'counter', | |
default: 0 | |
}); | |
const isEvenState = hawkeye({ | |
key: 'isEven', | |
get: ({ get }) => { | |
const count = get(counterState) | |
return Boolean(count % 2) ? 'odd' : 'even' | |
} | |
}) | |
const useIncrease = () => { | |
const setCounter = useHawkSetState(counterState) | |
const increase = (n = 1) => { | |
setCounter(count => count + n) | |
} | |
return increase | |
} | |
const useDecrease = () => { | |
const setCounter = useHawkSetState(counterState) | |
const decrease = (n = 1) => { | |
setCounter(count => count - n) | |
} | |
return decrease | |
} | |
export const Counter = () => { | |
const count = useHawkState(counterState) | |
const even = useHawkState(isEvenState) | |
const decrease = useDecrease() | |
const increase = useIncrease() | |
return ( | |
<> | |
<button onClick={() => decrease()}>-</button> | |
{count} is {even} | |
<button onClick={() => increase()}>+</button> | |
</> | |
) | |
} |
const reducer = (state, action) => { | |
switch (action) { | |
case 'incr': return state + 1; | |
case 'decr': return state - 1; | |
} | |
}; | |
const Counter = () => { | |
const [count, dispatch] = useReducer(reducer, 0); | |
return x` | |
<div> | |
<p>Count: ${count}</p> | |
<button onclick=${() => dispatch('incr')}>Increment</button> | |
</div> | |
`; | |
}; |
import { h, text, app } from "https://unpkg.com/hyperapp" | |
import { main, h1, button } from "https://unpkg.com/@hyperapp/html" | |
const Subtract = (state) => ({ ...state, count: state.count - 1 }) | |
const Add = (state) => ({ ...state, count: state.count + 1 }) | |
app({ | |
init: (count = 0) => ({ count }), | |
view: (state) => | |
main({}, [ | |
h1({}, text(state.count)), | |
button({ onclick: Subtract }, text("-")), | |
button({ onclick: Add }, text("+")), | |
]), | |
node: document.getElementById("app"), | |
}) |
import React from 'react' | |
import create from 'xoid' | |
import { useAtom } from '@xoid/react' | |
const | |
$count = create(0), | |
increment = () => $count.value++, | |
decrement = () => $count.value--; | |
const CounterReact = () => { | |
const count = useAtom($count) | |
return ( | |
<> | |
<div>{count}</div> | |
<button onClick={increment}>+</button> | |
<button onClick={decrement}>-</button> | |
</> | |
) | |
} |
import { defineComponent } from 'vue' | |
import { useAtom } from '@xoid/vue' | |
const CounterVue = defineComponent(() => { | |
const count = useAtom($count) // same `$count` above | |
return () => ( | |
<> | |
<div>{count.value}</div> | |
<button onClick={increment}>+</button> | |
<button onClick={decrement}>-</button> | |
</> | |
) | |
}) |
Pure React ?
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
const increment = ({ count }) => ({ count: count + 1 });
const decrement = ({ count }) => ({ count: count - 1 });
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<p>
{this.state.count}
<button onClick={() => this.setState(increment)}>+</button>
<button onClick={() => this.setState(decrement)}>-</button>
</p>
);
}
}
ReactDOM.render(<Counter />, document.getElementById('root'));
How about Svelte?
<p>
{{ count }}
<button on:click="set({count: count + 1})">+</button>
<button on:click="set({count: count - 1})">-</button>
</p>
<script>
export default {
data() {
return {
count: 0
}
}
}
</script>
Here's Marko:
class {
onCreate() {
this.state = { count: 0 };
}
increment(delta) {
this.state.count += delta;
}
}
<p>
${state.count}
<button on-click('increment', 1)>+</button>
<button on-click('increment', -1)>-</button>
</p>
To mount the Marko component:
require('./path/to/marko-counter').renderSync().appendTo(document.body)
DIO. v7.0.0
class Counter {
getInitialState () {
return {
count: 0
}
}
increment () {
return {
count: this.state.count + 1
}
}
decrement () {
return {
count: this.state.count - 1
}
}
render () {
return [
this.state.count,
h('button', {onClick: this.increment}, '+'),
h('button', {onClick: this.decrement}, '-')
]
}
}
dio.render(Counter);
How about Svelte?
There is a typo in the gist see https://gist.github.com/srdjan/1d10cbd42a2d695f696dee6b47fdc5e0#file-121-svetle-html
need to change sveTLe to sveLTe
and also it would be great to add svelte3 version
React with Effector
import React from "react";
import ReactDOM from "react-dom";
import { createStore, createEvent } from "effector";
import { createComponent } from "effector-react";
const increment = createEvent("increment");
const decrement = createEvent("decrement");
const resetCounter = createEvent("reset counter");
const counter = createStore(0)
.on(increment, state => state + 1)
.on(decrement, state => state - 1)
.reset(resetCounter);
const Counter = createComponent(counter, (props, counter) => (
<>
<div>{counter}</div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={resetCounter}>reset</button>
</>
));
Effector + React hooks:
import React from "react";
import ReactDOM from "react-dom";
import { createStore, createEvent, createApi } from "effector";
import { useStore } from "effector-react";
const $counter = createStore(0)
const increment = createEvent();
const decrement = createEvent();
$counter.on(increment, state => state + 1)
$counter.on(decrement, state => state - 1)
function Counter () {
const counter = useStore($counter)
return (
<>
<div>{counter}</div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</>
)
};
ReactDOM.render(<Counter />, document.body);
Count: <span id="count">0</span> <button onclick="count.innerText = +count.innerText+1">+</button> <button onclick="count.innerText = +count.innerText-1">-</button>
Gilbert That's awesome. The natural State of Light DOM is binding ID to a variable inside the window object. React guys won't tell you that. A similar mechanism is not available in the shadowRoot of Web Component. And that is great. I believe using getter and setter to IDs within web components can reproduce all the state management technique shown above. Just using getter and setter for defined IDs within a Shadow DOM, enter and exit strategy can be devised that can adopt any of above. Lets Discuss
Great stuff. I noticed something in 056-reausable.js. At line 21 there is a missing t letter from the component name. Also, 056-reausable.js has an extra a letter at the beginning.
thanks, fixed.
Awesome stuff. I noticed that, in 128-hooks-as-a-return-val.js and 133-fantasy-land.js, there should be square brackets around useState
calls.
xoid + React
import React from 'react'
import create from 'xoid'
import { useAtom } from '@xoid/react'
const
$count = create(0),
increment = () => $count.value++,
decrement = () => $count.value--;
const CounterReact = () => {
const count = useAtom($count)
return (
<>
<div>{count}</div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</>
)
}
xoid + Vue
import { defineComponent } from 'vue'
import { useAtom } from '@xoid/vue'
const CounterVue = defineComponent(() => {
const count = useAtom($count) // same `$count` above
return () => (
<>
<div>{count.value}</div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</>
)
})
thanks, I added xoid
examples
@jbucaran ✅