Lightweight solution to create custom React context. Build with typescript, untop useContext and useSyncExternalStore.
Install it with :
npm i archa
To create your custom context use the createStore
function. It takes 2
arguments:
- initialSate, an object with your states.
- dispatch (optional), a callback exposing
set
andget
methods to create a list of functions to mutate your states.
const { Provider, useStore } = createStore({
string: ''
});
and return:
- Provider
- useStore, expose all state and a setStore method. Trigger a rerender of your component only when one of the returned state is mutate. If dispatch were provided setStore will not be expose.
- useDispatch, expose all dispatch functions
const [state1, setStore] = useStore((store) => [store.state1 store.setStore]);
const function1 = useDispatch((dispatch) => dispatch.function1);
...
setStore(({ string }) => ({ string: newString })
- [] Add a way to get selectors value.
- by changing useDispatch into useActions (name WIP)
- by creating a new useSelector hook. If so, should useDispatch use return value to update the store instead of using the set method ?
- [] Make the Provider be able to take value (
Partial<T_Store>
). - [] Add test.
import { createStore } from 'archa';
const { Provider, useStore } = createStore({
count: 0,
});
function Count() {
const setStore = useStore((store) => store.setStore);
return (
<>
<button onClick={() => setStore(({ count }) => ({ count: count + 1 }))}>
Increment count
</button>
<button onClick={() => setStore(({ count }) => ({ count: count - 1 }))}>
Decrement count
</button>
</>
);
}
function CountDisplay() {
const count = useStore((store) => store.count);
return <span>{`The current count is ${count}.`}</span>;
}
export function Counter() {
return (
<Provider>
<CountDisplay />
<Count />
</Provider>
);
}
import { createStore } from 'archa';
const { Provider, useStore, useDispatch } = createStore(
{
count: 0,
},
(set, get) => ({
addCount: () => {
const { count } = get();
set({ count: count + 1 }):
},
removeCount: () => {
const { count } = get();
set({ count: count - 1 }):
}
}),
);
function Count() {
const [ addCount, removeCount ] = useDispatch((dispatch) => [
dispatch.addCount, dispatch.removeCount
]);
return (
<button onClick={addCount}>
Increment count
</button>
<button onClick={removeCount}>
Decrement count
</button>
);
}
function CountDisplay() {
const count = useStore((store) => store.count);
return (
<span>{`The current count is ${count}.`}</span>
);
}
export function Counter() {
return (
<Provider>
<CountDisplay />
<Count />
</Provider>
);
}