You build a generic provider that memoizes its value object, but you split state and dispatch into two contexts so dispatch-only consumers don't re-render. A dispatch-only child still re-renders whenever state changes. The dispatch comes from useReducer. What is the actual bug?
function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, init);
return (
<StateCtx.Provider value={state}>
<DispatchCtx.Provider value={{ dispatch }}>
{children}
</DispatchCtx.Provider>
</StateCtx.Provider>
);
}