I am trying to update the Child
component if the reducer function in Parent
component runs successfully.
function reducer(state, action) {
if (action.type === "something") {
try {
action.cb();
return { ...state, updated: true };
} catch (error) {
action.cb(error)
}
}
}
function Parent() {
const [state, dispatch] = useReducer(reducer)
return <Child dispatch={dispatch}></Child>
}
function Child({ dispatch }) {
const [state, setState] = useState(false)
function handleClick () {
function cb(err) {
if (!err) {
setState(true)
}
}
dispatch({ type: "something", cb: cb });
}
return <button onClick={handleClick}>Click me</button>;
}
When I run the above code I get a warning:
Warning: Cannot update a component (Child) while rendering a different
component (Parent)
How can I update the Child
component’s state if there is no error in the reducer
function?
2
Answers
Do Not Put Non-Serializable Values in State or Actions
You can subscribe to the changes of the
updated
state in the child component and set its state.There is no need to use
try/catch
, if theupdated
state is not updated correctly, it still staysfalse
value.stackblitz
See also:
Reducers are to be considered pure functions… don’t pass in functions and invoke them from within your reducer function. Issue the side-effects appropriately via the
useEffect
hook or in an event callback, e.g. likehandleClick
.In this case, issue the side-effect in the
handleClick
callback, and if that is successful, dispatch the action to update your state.