Instantly share code, notes, and snippets.

Embed
What would you like to do?
100 Counter Apps -state management
...
Different
Counter
Implementations
...
import { app, main, h1, button } from "hyperapp.V2"
app({
init: 0,
view: state => main({},
h1({}, state),
button({ onclick: state => state - 1, disabled: state <= 0 }, ""),
button({ onclick: state => state + 1 }, "")),
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>
</>)
@mweststrate

This comment has been minimized.

Show comment
Hide comment
@mweststrate

mweststrate Nov 19, 2016

Suggestion, MobX + React :) ? That is a bit more straight-forward compared to VirtualDOM

// counter: mobx-react implementation

import { observable } from 'mobx';
import { observer } from 'mobx-react';
import React from 'react'
import {render} from 'react-dom'

const state = { n: 0 };
const onclick = () => state.n++;

const view = observer(() => <div>
  <h1>clicked {state.n} times</h1>
  <button onclick={onclick}>click me!</button>
</div>)

render(
  <view />,
  document.querySelector('#app')
);

mweststrate commented Nov 19, 2016

Suggestion, MobX + React :) ? That is a bit more straight-forward compared to VirtualDOM

// counter: mobx-react implementation

import { observable } from 'mobx';
import { observer } from 'mobx-react';
import React from 'react'
import {render} from 'react-dom'

const state = { n: 0 };
const onclick = () => state.n++;

const view = observer(() => <div>
  <h1>clicked {state.n} times</h1>
  <button onclick={onclick}>click me!</button>
</div>)

render(
  <view />,
  document.querySelector('#app')
);
@srdjan

This comment has been minimized.

Show comment
Hide comment
@srdjan

srdjan Nov 25, 2016

@mweststrate - oh, nice ! updated - thank you.
MobX is lovely...

Owner

srdjan commented Nov 25, 2016

@mweststrate - oh, nice ! updated - thank you.
MobX is lovely...

@jorgebucaran

This comment has been minimized.

Show comment
Hide comment
@jorgebucaran

jorgebucaran Feb 12, 2017

@srdjan Minor suggestion, HyperApp+JSX looks neater. 👋

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>
})

jorgebucaran commented Feb 12, 2017

@srdjan Minor suggestion, HyperApp+JSX looks neater. 👋

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>
})
@roman01la

This comment has been minimized.

Show comment
Hide comment
@roman01la

roman01la Feb 24, 2017

ClojureScript + Rum counter

(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"))

roman01la commented Feb 24, 2017

ClojureScript + Rum counter

(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"))
@jorgebucaran

This comment has been minimized.

Show comment
Hide comment
@jorgebucaran

jorgebucaran Feb 24, 2017

@roman01la What's atom 0? Is that how you declare the initial value?

jorgebucaran commented Feb 24, 2017

@roman01la What's atom 0? Is that how you declare the initial value?

@roman01la

This comment has been minimized.

Show comment
Hide comment
@roman01la

roman01la Feb 24, 2017

@jbucaran yes, Atom is a reference type that holds an immutable value

roman01la commented Feb 24, 2017

@jbucaran yes, Atom is a reference type that holds an immutable value

@quarterto

This comment has been minimized.

Show comment
Hide comment
@quarterto

quarterto Feb 24, 2017

shameless plug for enviante:

import createStore from 'enviante';
import {createObserve} from 'enviante-react';
import React from 'react';
import {render} from 'react-dom';

const store = createStore({count: 0});
const observe = createObserve(store);

const Counter = observe(props, ({subscribe, dispatch}) => <div>
    <h1>{subscribe('count')}</h1>
    <button onclick={() => dispatch('count', count => count + 1)}>+</button>
    <button onclick={() => dispatch('count', count => count - 1)}>-</button>
</div>);

render(<Counter />, document.querySelector('main'));

quarterto commented Feb 24, 2017

shameless plug for enviante:

import createStore from 'enviante';
import {createObserve} from 'enviante-react';
import React from 'react';
import {render} from 'react-dom';

const store = createStore({count: 0});
const observe = createObserve(store);

const Counter = observe(props, ({subscribe, dispatch}) => <div>
    <h1>{subscribe('count')}</h1>
    <button onclick={() => dispatch('count', count => count + 1)}>+</button>
    <button onclick={() => dispatch('count', count => count - 1)}>-</button>
</div>);

render(<Counter />, document.querySelector('main'));
@lukeed

This comment has been minimized.

Show comment
Hide comment
@lukeed

lukeed Feb 24, 2017

CounterMVC

lukeed commented Feb 24, 2017

CounterMVC

@yyx990803

This comment has been minimized.

Show comment
Hide comment
@yyx990803

yyx990803 Feb 24, 2017

new Vue({
  data: { count: 0 },
  template: `
    <p>
      {{ count }}
      <button @click="count++">+</button>
      <button @click="count--">-</button>
    </p>
   `
}).$mount('#app')

Or

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')

Note: this also doesn't require any build step.

yyx990803 commented Feb 24, 2017

new Vue({
  data: { count: 0 },
  template: `
    <p>
      {{ count }}
      <button @click="count++">+</button>
      <button @click="count--">-</button>
    </p>
   `
}).$mount('#app')

Or

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')

Note: this also doesn't require any build step.

@tivac

This comment has been minimized.

Show comment
Hide comment
@tivac

tivac Feb 25, 2017

mithril

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-- }, "-")
    )
})

live demo

tivac commented Feb 25, 2017

mithril

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-- }, "-")
    )
})

live demo

@adamdicarlo

This comment has been minimized.

Show comment
Hide comment
@adamdicarlo

adamdicarlo Feb 25, 2017

This is awesome! One bug: There's a missing closing back-tick in 6-choo-choo-counter.js (should be at end of line 21)

adamdicarlo commented Feb 25, 2017

This is awesome! One bug: There's a missing closing back-tick in 6-choo-choo-counter.js (should be at end of line 21)

@gilbert

This comment has been minimized.

Show comment
Hide comment
@gilbert

gilbert Feb 25, 2017

Vanilla.js

Count: <span id="count">0</span>
<button onclick="count.innerText = +count.innerText+1">+</button>
<button onclick="count.innerText = +count.innerText-1">-</button>

gilbert commented Feb 25, 2017

Vanilla.js

Count: <span id="count">0</span>
<button onclick="count.innerText = +count.innerText+1">+</button>
<button onclick="count.innerText = +count.innerText-1">-</button>
@foxdonut

This comment has been minimized.

Show comment
Hide comment
@foxdonut

foxdonut Feb 25, 2017

I hope the vanilla js one is tongue-in-cheek... because you'd have to go fishing in the DOM to get your data back, that'd become a real mess real quick in a real app.

foxdonut commented Feb 25, 2017

I hope the vanilla js one is tongue-in-cheek... because you'd have to go fishing in the DOM to get your data back, that'd become a real mess real quick in a real app.

@polytypic

This comment has been minimized.

Show comment
Hide comment
@polytypic

polytypic Feb 25, 2017

Cool. As the developer of Calmm, I'd like to point out a couple of important details that are probably not immediately obvious just by looking at the code.

The first thing to understand is that the way state can be passed to components in Calmm via (lensed) atoms makes it possible to plug those components into application specific state fairly flexibly using lenses. The Counter component only assumes that it gets access to a numeric variable, but that variable can be adapted to mean many things. The shopping cart example shows how the Counter component can be adapted to control items in a shopping cart. In neither of the two uses of Counter in that example is the state that the component manipulates just a number.

The second thing to understand is that the Counter function that implements the component is only called by React when the component is mounted. In other words, the Counter function is not called for each change of the counter value. In fact, when the counter value changes, only the VDOM of the <div>Count: {value}</div> element is recomputed and the corresponding DOM element is then updated. The way observables can be embedded into VDOM in Calmm means that VDOM updates can easily be made almost optimal.

Here is a slightly fixed version of the example:

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"))

I moved the construction of the state atom outside of the component to emphasize that the Counter component can be a referentially transparent function. However, it is typical to define defaults, because that makes it easier to try out components, and it is also perfectly possible to create components that have local state that persists only for the duration that a component remains mounted.

polytypic commented Feb 25, 2017

Cool. As the developer of Calmm, I'd like to point out a couple of important details that are probably not immediately obvious just by looking at the code.

The first thing to understand is that the way state can be passed to components in Calmm via (lensed) atoms makes it possible to plug those components into application specific state fairly flexibly using lenses. The Counter component only assumes that it gets access to a numeric variable, but that variable can be adapted to mean many things. The shopping cart example shows how the Counter component can be adapted to control items in a shopping cart. In neither of the two uses of Counter in that example is the state that the component manipulates just a number.

The second thing to understand is that the Counter function that implements the component is only called by React when the component is mounted. In other words, the Counter function is not called for each change of the counter value. In fact, when the counter value changes, only the VDOM of the <div>Count: {value}</div> element is recomputed and the corresponding DOM element is then updated. The way observables can be embedded into VDOM in Calmm means that VDOM updates can easily be made almost optimal.

Here is a slightly fixed version of the example:

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"))

I moved the construction of the state atom outside of the component to emphasize that the Counter component can be a referentially transparent function. However, it is typical to define defaults, because that makes it easier to try out components, and it is also perfectly possible to create components that have local state that persists only for the duration that a component remains mounted.

@srdjan

This comment has been minimized.

Show comment
Hide comment
@srdjan

srdjan Feb 25, 2017

@polytypic thanks for comments - updated
I was planning a second round with examples that are more involving - todo app with external API for persistence was original plan
but now shopping cart looks more like it 😄

Owner

srdjan commented Feb 25, 2017

@polytypic thanks for comments - updated
I was planning a second round with examples that are more involving - todo app with external API for persistence was original plan
but now shopping cart looks more like it 😄

@gilbert

This comment has been minimized.

Show comment
Hide comment
@gilbert

gilbert Feb 25, 2017

Yes @foxdonut, definitely tongue-in-cheek :) It's also a parody of the succinctness that everyone is going for with their framework of choice. Without a defined set of objectives, Vanilla.js's example is just as valid as the others 😄

gilbert commented Feb 25, 2017

Yes @foxdonut, definitely tongue-in-cheek :) It's also a parody of the succinctness that everyone is going for with their framework of choice. Without a defined set of objectives, Vanilla.js's example is just as valid as the others 😄

@foxdonut

This comment has been minimized.

Show comment
Hide comment
@foxdonut

foxdonut Feb 26, 2017

Great stuff @mindeavor :) totally agree!

foxdonut commented Feb 26, 2017

Great stuff @mindeavor :) totally agree!

@dmitriid

This comment has been minimized.

Show comment
Hide comment
@dmitriid

dmitriid Feb 26, 2017

In a twitter conversation someone mentioned this repo: https://github.com/adrianmcli/omg-counters

I wonder if this gist could me merged there

dmitriid commented Feb 26, 2017

In a twitter conversation someone mentioned this repo: https://github.com/adrianmcli/omg-counters

I wonder if this gist could me merged there

@joaomilho

This comment has been minimized.

Show comment
Hide comment
@joaomilho

joaomilho Feb 26, 2017

Act's <1.0 (https://github.com/act-framework/act/) version if you wanna add:

const view = (count) =>
  ['p', [
    ['h1', count],
    ['button', {click: {add: 1}}, '+'],
    ['button', {click: {add: -1}}, '-']
  ]]

const reducer = (state, {type, payload}) =>
  type === 'add' ? state + payload : state

main(view, { model: 0, reducer })

joaomilho commented Feb 26, 2017

Act's <1.0 (https://github.com/act-framework/act/) version if you wanna add:

const view = (count) =>
  ['p', [
    ['h1', count],
    ['button', {click: {add: 1}}, '+'],
    ['button', {click: {add: -1}}, '-']
  ]]

const reducer = (state, {type, payload}) =>
  type === 'add' ? state + payload : state

main(view, { model: 0, reducer })
@adamdicarlo

This comment has been minimized.

Show comment
Hide comment
@adamdicarlo

adamdicarlo Feb 27, 2017

Where does 1b-calmm-counter-elm come from? As near as I can tell, https://github.com/polytypic/elm-reactive-dom-with-lensed-state-toy ? @polytypic

adamdicarlo commented Feb 27, 2017

Where does 1b-calmm-counter-elm come from? As near as I can tell, https://github.com/polytypic/elm-reactive-dom-with-lensed-state-toy ? @polytypic

@polytypic

This comment has been minimized.

Show comment
Hide comment
@polytypic

polytypic Feb 28, 2017

@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.

polytypic commented Feb 28, 2017

@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.

@jorgebucaran

This comment has been minimized.

Show comment
Hide comment
@jorgebucaran

jorgebucaran Mar 15, 2017

@srdjan Hi 👋! Can we update the code in hyperapp's example? The part that says update, should be actions. That's it. 🙏

jorgebucaran commented Mar 15, 2017

@srdjan Hi 👋! Can we update the code in hyperapp's example? The part that says update, should be actions. That's it. 🙏

@srdjan

This comment has been minimized.

Show comment
Hide comment
@srdjan

srdjan Mar 18, 2017

@jbucaran

Owner

srdjan commented Mar 18, 2017

@jbucaran

@renaudtertrais

This comment has been minimized.

Show comment
Hide comment
@renaudtertrais

renaudtertrais Mar 24, 2017

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'));

live demo

renaudtertrais commented Mar 24, 2017

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'));

live demo

@cristinecula

This comment has been minimized.

Show comment
Hide comment
@cristinecula

cristinecula Mar 25, 2017

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>

cristinecula commented Mar 25, 2017

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>
@patrick-steele-idem

This comment has been minimized.

Show comment
Hide comment
@patrick-steele-idem

patrick-steele-idem Mar 25, 2017

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>

Try Online

To mount the Marko component:

require('./path/to/marko-counter').renderSync().appendTo(document.body)

patrick-steele-idem commented Mar 25, 2017

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>

Try Online

To mount the Marko component:

require('./path/to/marko-counter').renderSync().appendTo(document.body)
@thysultan

This comment has been minimized.

Show comment
Hide comment
@thysultan

thysultan Mar 26, 2017

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);

thysultan commented Mar 26, 2017

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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment