If I have the following code
function MyApp() {
const [state, setState] = useState({name:'', updatedField:''});
useEffect(() => {
save(); //<---- endless loop here
}, [state]);
const save = async () => {
var response = await api.save(state);
var newState = {...state};
newState.updatedField = response.updatedField;
setState(newState);
}
const onSaveBtnClicked = (event) => {
var newState = {...state};
newState.name = event.target.value;
setState(newState);
}
}
The object 'state' is being saved via my api when it is changed, but the act of saving to the api requires updating the 'state' object. This obviously creates an endless loop.
What is the best practice here considering I have no way of providing a callback when I update the state using setState?
I'd separate the updatedField
out of the state
and put it into a different variable:
function MyApp() {
const [state, setState] = useState({name:'', /* include other fields here */});
const [updatedField, setUpdatedField] = useState('');
useEffect(save, [state]); // don't pass `state` to `save`
// since `save` doesn't take any parameters
const save = async () => {
var response = await api.save(state);
setUpdatedField(response.updatedField);
}
Then, wherever you're referring to state.updatedField
, instead refer to the standalone updatedField
identifier.
(make sure to catch possible asynchronous errors too - you don't want possible unhandled rejections)
I think I cam see how the loop happens:
I'm not sure why you need to call setState at the end of save. Does the api call in save change the state?
This is the solution I went for in the end.
function MyApp() {
const [state, setState] = useState(
{
needsSaving:false,
obj :{
name:'',
updatedField:''
}
});
useEffect(() => {
if(state.needsUpdate)
save();
}, [state.needsSaving]);
const save = async () => {
var response = await api.save(state.obj);
var newState = {...state};
newState.obj.updatedField = response.updatedField;
newState.needsSaving = false;
setState(newState);
}
const onSaveBtnClicked = (event) => {
var newState = {...state};
newState.obj.name = event.target.value;
newState.needsSaving = true;
setState(newState);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.