I want to fetch data when a state value changed.
This is easy approach since I can use useEffect
and tell it to run when the state value changes. something like this
useEffect(() => {
fetch(url,(result) => {
// this is callback function when data fetched
});
},[value]);
and somewhere in my render, I call setValue
after the user clicks a button.
But in my situation, value
has no default value so it's undefined
the first time, My API provides the initial value for value
. So the first time the useEffect
must set value
too.
useEffect(() => {
fetch(url,({value, ...data}) => {
// this is callback function when data fetched
setData(data);
setValue(value); // <- this line make loop since value is an object
// But I need to set value for initial value that came from server
});
},[value]);
And this makes an infinite loop since I'm changing value
on effect which depends on value.
In short
1-I get my initial value
from the API call
2-I need to re-call the API after the value
is changed by user click.
These 2 condition makes an infinite loop, How I can approach this?
UPDATED
The value is an object that contains a year and month and its initial value is based on the user config in the database. It's something like {month: 10, year: 2022}
and the user can change it in UI to navigate to other months.
CodePudding user response:
I you want to fetch something when value changes, I'd rather call it once, when user changes the value
object.
function fetchValue(oldValue) {
fetch(url, ({ value, ...data }) => {
setData(data)
setValue(value)
})
}
useEffect(() => {
// initial call to the API
fetchValue()
}, [])
// Later...
<button onClick={() => {
const newValue = updateValue(value)
setValue(newValue)
fetchValue(newValue)
}} />
or if you want to centralise effect handling with useEffect, you can split user-local value from what is returned from the server:
const [userValue, setUserValue] = useState()
const [serverValue, setServerValue] = useState()
useEffect(() => {
fetch(url, ({ value, ...data }) => {
setServerValue(value)
setData(data)
})
}, [userValue])
const actualValue = serverValue || userValue
<button onClick={() => {
setServerValue(undefined)
setUserValue(updateValue(actualValue))
}} />
CodePudding user response:
You can check if the value is `undefined`. If it's not you can set its value.
Something like this:
useEffect(() => {
fetch(url,({fetchedvalue, ...data}) => {
// this is callback function when data fetched
setData(data);
if (fetchedvalue == undefined){
setValue(fetchedvalue); // <- this line make loop since value is an object
// But I need to set value for initial value that came from server
}
});
},[value]);