Last active
July 2, 2020 11:20
-
-
Save myobie/cc50f828cc074072410bb22d92d7ec58 to your computer and use it in GitHub Desktop.
Make a little state object which can be updated through Immer's produce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import produce, { Draft, Immutable } from 'immer' | |
type Updater<S> = (state: Draft<S>) => void | S | |
type UpdateCallback<S> = (state: Immutable<S>) => void | |
type State<T> = { | |
current: Immutable<T>; | |
update: (updater: Updater<T>) => void; | |
onUpdate: (cb: UpdateCallback<T>) => void; | |
} | |
export default function<T> (initialState: T): State<T> { | |
let currentState: Immutable<T> = produce(initialState, draft => draft) as Immutable<T> | |
const callbacks: UpdateCallback<T>[] = [] | |
return { | |
get current () { | |
return currentState | |
}, | |
update (updater: Updater<T>) { | |
currentState = produce(currentState, updater) as Immutable<T> | |
callbacks.forEach(cb => { | |
cb(currentState) | |
}) | |
}, | |
onUpdate (cb: UpdateCallback<T>) { | |
callbacks.push(cb) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import createState from './create-state' | |
describe('createState', function () { | |
it('can be created', async function () { | |
const state = createState(5) | |
expect(state.current).to.equal(5) | |
}) | |
it('can be partially updated', async function () { | |
const state = createState({ | |
name: 'Alice', | |
age: 24 | |
}) | |
state.update(draft => { | |
draft.age += 1 | |
}) | |
expect(state.current.name).to.equal('Alice') | |
expect(state.current.age).to.equal(25) | |
}) | |
it('can notify when updated', async function () { | |
const state = createState(1) | |
const values: number[] = [] | |
state.onUpdate(newState => { | |
values.push(newState) | |
}) | |
state.update(draft => ++draft) | |
state.update(draft => ++draft) | |
expect(values).to.eql([2, 3]) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment