This implementation makes use of useSyncExternalStore()
that is available in React 18 or via shim.
Store declaration:
// CounterStore.js
import { createStore } from 'thelib'
let [CounterProvider, useCounter] = createStore((set) => ({
counter: 0,
increment() {
set(state => ({ counter: state.counter + 1 }));
},
}))
export { CounterProvider, useCounter }
Store consumption:
// CounterView.jsx
import { CounterProvider, useCounter } from './CounterStore'
function View() {
return (
<CounterProvider>
<Output />
<Controls />
</CounterProvider>
)
}
function Output() {
// only gets updated with selector has changed
let value = useCounter(state => state.counter)
return <span>{value}</span>
}
function Controls() {
// never gets re-rendered
let increment = useCounter(state => state.increment)
return <button onClick={increment}>+</button>
}