I've been following a guide to pass down a reducer to child components with useContext, but when dispatching from a child component, it did not seem to re-render the parent component.
The state itself seems to be correctly updating when dispatching from the Child component (as done by console.logging state.count), but the parent component does not reflect the change in state.
I've tried passing down a dispatch function as a prop to Child, and that did update App.js, but I was thinking that my approach was cleaner and I could be doing something wrong instead. I've also put {state.count}
in Child.js and it did get updated properly, but for this situation I need it in the parent component. Here is the code:
App.js
import React, { useReducer } from 'react';
import { StateProvider } from './reducer';
import Child from './Child'
function App() {
const reducer = (state, action) => {
switch (action.type) {
case 'add':
console.log(state.count+1)
return {...state, count: state.count + 1}
default:
throw new Error();
}
}
const initialState = {count: 1};
const [state, dispatch] = useReducer(reducer, initialState)
return (
<StateProvider initialState={initialState} reducer={reducer}>
<div className="App">
{state.count}
<Child></Child>
</div>
</StateProvider>
);
}
export default App;
reducer.js
import React, {createContext, useContext, useReducer} from 'react';
export const StateContext = createContext(null);
export const StateProvider = ({reducer, initialState, children}) => (
<StateContext.Provider value={useReducer(reducer, initialState)}>
{children}
</StateContext.Provider>
);
export const useStateValue = () => useContext(StateContext);
Child.js
import React from 'react';
import { useStateValue } from './reducer';
export default function Child(props) {
const [state, dispatch] = useStateValue();
return (
<button onClick={() => dispatch({type: 'add'})}>Increment</button>
)
}