There's some data coming from long polling every 5 seconds and I would like my component to dispatch an action every time one item of an array (or the array length itself) changes. How do I prevent useEffect from getting into infinity loop when passing an array as dependency to useEffect but still manage to dispatch some action if any value changes?
useEffect(() => { console.log(outcomes) }, [outcomes])
where outcomes
is an array of IDs, like [123, 234, 3212]
. The items in array might be replaced or deleted, so the total length of the array might - but don't have to - stay the same, so passing outcomes.length
as dependency is not the case.
outcomes
comes from reselect's custom selector:
const getOutcomes = createSelector( someData, data => data.map(({ outcomeId }) => outcomeId) )
To pass an array to useEffect dependency list in React, we can pass in the array state into the dependencies list. We have the nums array state we created with the useState hook. Then we call useEffect with a callback that logs the current value of nums .
This array will re-run useEffect, if the values inside it changes. This will work perfectly fine when the values passed in the dependency array are of type boolean, string or numbers. But it will have some gotchas when you are dealing with complex values such as objects or arrays.
Empty dependency array So what happens when the dependency array is empty? It simply means that the hook will only trigger once when the component is first rendered. So for example, for useEffect it means the callback will run once at the beginning of the lifecycle of the component and never again.
The useEffect hook allows you to perform side effects in a functional component. There is a dependency array to control when the effect should run. It runs when the component is mounted and when it is re-rendered while a dependency of the useEffect has changed.
One of the arguments that the useEffect accepts, after the callback function is the dependency array. This array defines the list of variables that if changed will trigger the callback function. Let us take a look at some of the parameters that can be passed in place of the dependency array, and how it affects the hook itself. 1.
These additional rules help you catch bugs early like helping you to know what needs to be added to your dependency array - the exhaustive-deps rule. There's more than one hook that uses a dependency array concept, but chances are you'll learn about the dependency array when you learn useEffect which is often one of the first hooks people learn:
This answer is wrong, useRef ().current can not be used in a dependency array: medium.com/welldone-software/… @flyingsheep It's your argument that is wrong. Did you read the code and try running the demo? ref.current is a middle man variable that is used to store the new value which invokes the effect callback depend on the equality check.
Spreading the array is no good. App starts with an empty array as default, so useEffect will throw error about different number of dependencies between rerenders. You can pass JSON.stringify (outcomes) as the dependency list: useEffect ( () => { console.log (outcomes) }, [JSON.stringify (outcomes)]) I'm quite sure this is the answer the OP wants.
You can pass JSON.stringify(outcomes)
as the dependency list:
Read more here
useEffect(() => { console.log(outcomes) }, [JSON.stringify(outcomes)])
Another ES6 option would be to use template literals to make it a string. Similar to JSON.stringify()
, except the result won't be wrapped in []
useEffect(() => { console.log(outcomes) }, [`${outcomes}`])
Another option, if the array size doesn't change, would be to spread it in:
useEffect(() => { console.log(outcomes) }, [ ...outcomes ])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With