Skip to content

Instantly share code, notes, and snippets.

@staydecent
Created June 17, 2020 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save staydecent/ed25b3daeeffa6a27d6ed39596f34e6d to your computer and use it in GitHub Desktop.
Save staydecent/ed25b3daeeffa6a27d6ed39596f34e6d to your computer and use it in GitHub Desktop.
import equal from '@app-elements/equal'
import { useEffect, useReducer, useRef } from 'preact/compat'
export function useMappedState (store, mapper) {
const [, forceRender] = useReducer(s => s + 1, 0)
const initialState = mapper(store.getState())
const mappedStateRef = useRef(initialState)
useEffect(() => {
function checkForUpdates () {
const nextState = mapper(store.getState())
if (!equal(nextState, mappedStateRef.current)) {
mappedStateRef.current = nextState
forceRender({})
}
}
checkForUpdates()
const unsubscribe = store.subscribe(checkForUpdates)
return () => unsubscribe()
}, [store, mapper])
return mapper(store.getState())
}
export function useCursor (store, path) {
const steps = path.split('.')
const cursor = (state) => steps.reduce((acc, cur) => {
if (acc != null && acc.hasOwnProperty(cur)) {
return acc[cur]
} else {
return undefined
}
}, state)
const setter = (val) => {
const copy = store.getState()
steps.reduce(
(obj, prop, idx) => {
obj[prop] = obj[prop] || {}
if (steps.length === (idx + 1)) {
obj[prop] = val
}
return obj[prop]
},
copy
)
store.setState(copy, { cursor: path })
}
const value = useMappedState(store, cursor)
return [value, setter]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment