Skip to content

Instantly share code, notes, and snippets.

@viniciusCamargo
Last active February 11, 2021 10:26
Show Gist options
  • Save viniciusCamargo/741d9909f07179879f31d4f59f743dc3 to your computer and use it in GitHub Desktop.
Save viniciusCamargo/741d9909f07179879f31d4f59f743dc3 to your computer and use it in GitHub Desktop.
atom: Redux-inspired state manager with simpler API
const l = console.log.bind(this)

const _a = atom({ list: [1,2,3,4], bool: false, key: 'value' })

_a.subscribe(() => l(_a.get())) // will log the state on every change

_a.get('key') // 'value'
const { key } = _a.get() // key === { key: 'value' }

_a.set({ key: 'other value' })
_a.get() // { list: [1,2,3,4], bool: false, key: 'other value' }

_a.set((oldState) => ({ bool: !oldState.bool }))
_a.get() // { list: [1,2,3,4], bool: true, key: 'other value' }


_a.get('list').map(l)) // will log 1, 2, 3, 4

UMD

Production: https://s3-sa-east-1.amazonaws.com/camargo-public/atom/atom.min.js

Development: https://s3-sa-east-1.amazonaws.com/camargo-public/atom/atom.js

const atom = (initialState = {}) => {
let state = initialState
let listeners = []
const get = (i) => {
if (i) {
if (Object.keys(state).includes(i)) {
return state[i]
}
throw new Error(`There's no "${i}" key in state.`)
}
return state
}
const set = (e) => {
if (!e) {
throw new Error(`No element to set in state.`)
}
if (typeof e === 'function') {
return set(e(state))
}
state = { ...state, ...e }
listeners.forEach(listener => listener())
}
const subscribe = (listener) => {
listeners.push(listener)
return () => {
listeners = listeners.filter(l => l !== listener)
}
}
return { get, set, subscribe }
}
const atom=(initialState={})=>{let state=initialState;let listeners=[];const get=(i)=>{if(i){if(Object.keys(state).includes(i)){return state[i]};throw new Error(`There's no "${i}" key in state.`)};return state};const set=(e)=>{if(!e){throw new Error(`No element to set in state.`)};if(typeof e==='function'){return set(e(state))};state={...state,...e};listeners.forEach(listener=>listener())};const subscribe=(listener)=>{listeners.push(listener);return()=>{listeners=listeners.filter(l=>l!==listener)}};return{get,set,subscribe}};
// with mithril.js
const l = console.log.bind(this)
const initialState = { value: 'banana', hello: 'world', nope: false, e: ['um', 'dois', 'tres'] }
const _a = atom(initialState)
_a.subscribe(() => l(_a.get()))
const handleInput = (e) => {
const { value } = e.target
_a.set({ value })
}
const handleButton = (oldState) => ({ nope: !oldState['nope'] })
const MyComponent = {
view() {
const { value, nope, e } = _a.get()
return m('div', [
m('input', { type: 'text', oninput: handleInput }),
m('p', value),
m('h1', _a.get('hello')),
m('button', { onclick: () => _a.set(handleButton) }, `toggle: ${nope}`),
e.map(p => m('p', p))
])
}
}
m.mount(document.getElementById('root'), MyComponent)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment