2 years ago
#66985
coltonyoung
React Context children re-rendering to initial state when updating context state
I'm having an issue where, whenever I update my context state within a hook (useEffect, useCallback, etc.), any other state updates that I make don't actually go through because the state for that component resets to initial state.
I have the following component which provides the message context, its provider, and exposes a hook to access the message state variable's value and setter:
const MessageContext = React.createContext<MessageContextProps>({
message: {} as IMessage,
setMessage: () => {},
});
export function MessageProvider(props: MessageProviderProps): JSX.Element {
const [message, setMessage] = useState<IMessage>({} as IMessage);
return <MessageContext.Provider value={{ message, setMessage }}>{props.children}</MessageContext.Provider>;
}
export function useMessage(): MessageContextProps {
return React.useContext(MessageContext);
}
My app is wrapped in the provider:
ReactDOM.render(
<React.StrictMode>
<ErrorBoundary>
<MessageProvider>
<App />
</MessageProvider>
</ErrorBoundary>
</React.StrictMode>,
document.getElementById('root')
);
Whenever I try to update the formData in my component (setFormData(newFormData)) in the same render cycle as I update the message state (setMessage()) from MessageContext, only the message state updates. The rest of my state updates don't re-render (specifically, the formData.changedValue value in the final paragraph tag), I think because it's getting reset to initial state.
export default function App(): JSX.Element {
const [formData, setFormData] = useState(INITIAL_STATE);
const { message, setMessage } = useMessage();
const [updateSuccessful, setUpdateSuccessful] = useState(false);
const handleSubmit = useCallback(
(event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
makeSomeAPICall(formData);
setUpdateSuccessful(true);
},
[formData]
);
useEffect(() => {
if (updateSuccessful) {
setFormData((current) => {
return {
...current,
changedValue: current.myField,
};
});
setMessage({
displayText: `Change Successful`,
type: 'success',
});
}
}, [updateSuccessful]);
return (
<>
<form onSubmit={handleSubmit}>
<div>
<select id='changeMe' value={formData.myField} onChange={() => setFormData(formData.myField)}>
<option value='Y'>Y</option>
<option value='N'>N</option>
</select>
<button type='submit'>Submit</button>
</form>
<p>Changed Value: {formData.changedValue}</p>
</>
);
}
reactjs
react-hooks
render
react-context
reactjs
react-hooks
render
react-context
0 Answers
Your Answer