Skip to content

Instantly share code, notes, and snippets.

@srdjan
Last active May 6, 2024 05:13
Show Gist options
  • Save srdjan/1d10cbd42a2d695f696dee6b47fdc5e0 to your computer and use it in GitHub Desktop.
Save srdjan/1d10cbd42a2d695f696dee6b47fdc5e0 to your computer and use it in GitHub Desktop.
100+ different js counter apps...
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>
</>
)
})
@zoltanrendes
Copy link

zoltanrendes commented Mar 28, 2020

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.

@srdjan
Copy link
Author

srdjan commented Mar 28, 2020

thanks, fixed.

@onurkerimov
Copy link

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

@srdjan
Copy link
Author

srdjan commented Nov 5, 2023

thanks, I added xoid examples

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment