0.0.1 • Published 4 years ago
@intouchg/substate v0.0.1
@novas/substate
1kb subscription-based state hooks for React, forked from @novas/substate
Installation
yarn add @intouchg/substateMotivation
Allow child components to create and subscribe to keyed stateful values on a parent ContextProvider and re-render only when necessary, without memoization at the component level. 1kb and no dependencies.
Example
import {
useSubState,
useCreateSubState,
SubStateProvider,
} from '@intouchg/substate'
import { useRef, useEffect } from 'react'
const Parent = ({ children }) => {
const api = useCreateSubState()
return <SubStateProvider value={api}>{children}</SubStateProvider>
}
const Child = ({ id, children }) => {
const { state, setState, store } = useSubState(id)
const renderCount = useRef(0)
useEffect(() => void renderCount.current++)
return (
<p>
<h2>Child {id}</h2>
<span>Render count: {renderCount.current}</span>
<span>Current value: {state}</span>
<button onClick={() => setState(Math.random())}>
Re-render child {id}
</button>
</p>
)
}
const Page = () => (
<Parent>
<Child id="1" />
<Child id="2" />
<Child id="3" />
<Child id={3} />
</Parent>
)Usage
The store must be an object. Do not mutate state directly, use the setter functions.
useCreateSubStateto create the store api and pass it to aSubStateProvider
import { useCreateSubState, SubStateProvider } from '@intouchg/substate'
const MyComponent = ({ children }) => {
const api = useCreateSubState()
return <SubStateProvider value={api}>{children}</SubStateProvider>
}useSubStateto create and subscribe to keyed values in the store from a child component. It will only cause re-renders when the store value with that specific key changes. Multiple components can subscribe to the same key.
const { state, setState } = useSubState('test')setStateaccepts a value or merging function, just like React.
setState({ hello: 'world' })
setState((currentState) => currentState++)useSubStatealso returns the entire store and store update function.
const { state, setState, store, setStore } = useSubState('test')
// state === store.testsetStoreaccepts a key and a value or merging function. Astringkey will update a single key in the store, whileundefinedwill update the entire store. Updating the entire store will re-render all components subscribed to that store. The store must be an object.
setStore('test', { hello: 'world' })
setStore(undefined, { test: { hello: 'world' } })useSubStatewithout a key will subscribe to the entire store. This will cause re-renders any time a value in the store changes, and allow setting the entire store withsetState. The store must be an object.
const { state, setState, store, setStore } = useSubState()
// state === store
// setState === ((value) => setStore(undefined, value))useSubStateaccepts an optional initial value. If two components with the same key have different initial values, the component that mounts later will overwrite the first. This works for individual keys, or the entire store. The store must be an object.
const { state: count, setState: setCount } = useSubState('test', 2)
const { store, setStore } = useSubState(undefined, { test: 1 })0.0.1
4 years ago
0.0.1-alpha.1
4 years ago