I'm fetching some data from an API, but since I am using this data to update a state within a useEffect
, this state becomes a required dependency, which causes a circular loop.
state is updated -> useEffect is called -> state is updated ...
I read a lot of answers and articles about that, but I couldn't find an answer to my specific question.
This is my initial code:
let [state, setState] = React.useState<IDataSource[]>([])
React.useEffect(() => {
let dataSource: IDataSource[] = []
dataFetched.forEach((item, index) => {
// Some logic
})
setState(state.concat(dataSource))
}, [dataFetched, state])
Then I decided to update the state using a function called by useEffect
and passing an argument:
let [state, setState] = React.useState<IDataSource[]>([])
const updateData = (arg: IDataSource[] => {
setData(state.concat(arg))
}
React.useEffect(() => {
let dataSource: IDataSource[] = []
dataFetched.forEach((item, index) => {
//Some logic
})
updateData(dataSource)
}, [dataFetched, updateData])
This works, but since I have updateData
as a useEffect depency
I have to wrap the function with useCallback
:
const updateData = React.useCallback((arg: IDataSource[]) => {
setData(state.concat(arg))
}, [state])
React.useEffect(() => {
let dataSource: IDataSource[] = []
dataFetched.forEach((item, index) => {
//Some logic
})
updateData(dataSource)
}, [dataFetched, updateData])
But in this case I also have state
as a useCallback depency
and I'm back to the starting problem, a circular loop.
Apparently I should use React.useRef
when I have an array as useEffect dependency
, but state
is not just an array, it is actually a state, which is being set with useState
, so I don't know how to do that in this case or even if this is possible.
Is there a way to solve that?
You can remove data
from the useEffect
array and call setState
with an updater function like this setState(prevState => prevState.concat(dataSource))
const [state, setState] = React.useState<IDataSource[]>([])
React.useEffect(() => {
const dataSource: IDataSource[] = []
dataFetched.forEach((item, index) => {
// Some logic to fill the dataSource array ??
})
setState(prevState => prevState.concat(dataSource))
}, [dataFetched])