-
Star
(153)
You must be signed in to star a gist -
Fork
(10)
You must be signed in to fork a gist
-
-
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> | |
| </> | |
| ) | |
| }) |
@adamdicarlo Yes, (I believe) it comes from there. Note that the Elm toy example is just a quick hack to show how things could look like. The Elm toy version is neither as expressive (it lacks higher-order observables and first-class atoms) nor as algorithmically efficient (updates require recomputing more VDOM) as the Calmm JS version, but there is no reason why one couldn't implement the approach properly in a ML-style language. Note that mentioning people in gist comments doesn't (seem to) give notifications.
@srdjan Hi 👋! Can we update the code in hyperapp's example? The part that says update, should be actions. That's it. 🙏
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
Where does
1b-calmm-counter-elmcome from? As near as I can tell, https://github.com/polytypic/elm-reactive-dom-with-lensed-state-toy ? @polytypic