Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple counter: different implementations...
different implementations of the simple counter app... code verbosity vs expressiveness
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-- }, "-")
)
})
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 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"))
import { h, app } from "hyperapp"
app({
model: 0,
update: {
add: model => model + 1,
sub: model => model - 1
},
view: (model, actions) =>
<div>
<button onclick={actions.add}>+</button>
<h1>{model}</h1>
<button onclick={actions.sub} disabled={model <= 0}>-</button>
</div>
})
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" ]
]
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 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')
});
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())
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)
}
}
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 "+" ]
]
#r "../node_modules/fable-core/Fable.Core.dll"
#r "../node_modules/fable-react/Fable.React.dll"
#r "../node_modules/fable-elmish/Fable.Elmish.dll"
#r "../node_modules/fable-elmish-react/Fable.Elmish.React.dll"
open Fable.Core
open Fable.Import
open Elmish
type Msg = Increment | Decrement
let initialModel () = 0
let update (msg:Msg) model =
match msg with
| Increment -> model + 1
| Decrement -> model - 1
module R = Fable.Helpers.React
open Fable.Core.JsInterop
open Fable.Helpers.React.Props
let view model dispatch =
let onClick msg = OnClick <| fun _ -> msg |> dispatch
R.div []
[ R.button [ onClick Decrement ] [ unbox "-" ]
R.div [] [ unbox (string model) ]
R.button [ onClick Increment ] [ unbox "+" ] ]
open Elmish.React
Program.mkSimple initialModel update view
|> Program.withReact "app"
|> Program.run
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment