Reputation: 463
I have a warning on this nested setState pointing a "bad setState call" because I am calling a setState inside a setState, so I understand I must avoid that and take out the children setState from there, the problem is that the children is using the parent prevState for a conditional so I don't know how to solve this.
This is my code:
const setStateImageAndIndex = (state, image) => {
setSketchState(prevState => {
if (state.index !== undefined && prevState.index !== state.index) {
setCurrentSketchIndex(state.index);
}
const new_state = {
...prevState,
...state,
image: image
};
return new_state;
});
};
The warning is pointing the setCurrentSketchIndex(state.index);
explicitly, which is the function I want to take out from setSketchState. Thank you!
Upvotes: 0
Views: 26
Reputation: 463
According to the comments above from @GabrielePetrioli and @GiovanniEsposito, this solution seemed to be safer.
const setStateImageAndIndex = (state, image) => {
let updateCurrentSketchIndex = false;
setSketchState(prevState => {
if (state.index !== undefined && prevState.index !== state.index) {
updateCurrentSketchIndex = true;
}
const new_state = {
...prevState,
...state,
image: image
};
return new_state;
});
if (updateCurrentSketchIndex) {
setCurrentSketchIndex(state.index);
}
};
Upvotes: 0
Reputation: 2985
you can hold the previous state of the parent component in a useRef
and derivate the state in the child component passing that value down as a prop, for example:
function Parent() {
let [state, setState] = React.useState({ version: 1 });
let prevState = usePrevious(state.version);
return (
<div>
<p>Parent value: {state.version}</p>
<Child value={prevState} />
<button
onClick={() =>
setState({
version: state.version + 1
})
}
>
Update version
</button>
</div>
);
}
function Child(props) {
return (
<div>
<p>Child value: {props.value || "No value yet"}</p>
</div>
);
}
as we can see above, the parent component will update the state.version
in the button click and usePrevious
will hold the previous value:
function usePrevious(value) {
const ref = React.useRef();
React.useEffect(() => {
ref.current = value;
});
return ref.current;
}
Working example in: https://codesandbox.io/s/use-previous-hook-0iemv
Upvotes: 0
Reputation: 11166
prevState
in setSketchState
infact is the actual state of sketchState
(I mean the state setted by setSketchState
). So you could write something like:
const setStateImageAndIndex = (state, image) => {
if (state.index !== undefined && sketchState.index !== state.index) {
setCurrentSketchIndex(state.index);
}
setSketchState(prevState => {
const new_state = {
...prevState,
...state,
image: image
};
return new_state;
});
};
Upvotes: 2