I'll spare you the broader context as it's pretty simple. Using React hooks, the first dispatch here fires automatically and works just fine, but the second one doesn't. Context
is imported from another file, so I assume it's a (lowercase) context issue, but I don't know how to fix it?
const Component = props => {
const [, dispatch] = useContext(Context);
useEffect(() => {
document.title = state.title;
// eslint-disable-next-line react-hooks/exhaustive-deps
});
// this works
dispatch({ type: "UPDATE_TITLE", payload: "Not Click!" });
function onAddClick() {
// this doesn't work
dispatch({ type: "UPDATE_TITLE", payload: "CLICKED!" });
}
return (
<div>
<AddButton onClick={onAddClick} />
</div>
);
};
Here's the parent.
const Reducer = (state, action) => {
switch (action.type) {
case "UPDATE_TITLE":
state["title"] = action.payload;
return state;
default:
return state;
}
};
const initialState = {
title: "My Title"
};
export const Context = createContext(initialState);
const App = () => {
const [state, dispatch] = useReducer(Reducer, initialState);
return (
<Context.Provider value={[state, dispatch]}>
<Component />
</Context.Provider>
);
};
export default App;
Console logs fire in the correct reducer case in both cases, but only the one marked 'this works' will actually update the state properly, the other one fails silently.
Fixed: https://codesandbox.io/s/cranky-wescoff-9epf9?file=/src/App.js
It looks like you are attempting to mutate state directly. Instead try to return a new object that is the result of the changes from the action applied to the old state.
Alternatively, use produce from immerjs to give you the ability to write your reducer in this mutable style.