Today I learned: you can watch for nested properties changing in React's useEffect()
hook by using dot notation in the dependency array, like so:
// hook runs whenever someValue.someNestedValue is updated
useEffect(()=> {
// do something
}, [someValue.someNestedValue])
React's useEffect()
hook lets you perform a side-effect in a functional component. That is, whenever the component updates, whatever code you put in the useEffect()
hook executes.
By default, the hook runs on every component update, which for performance reasons we should avoid:
useEffect(()=> {
// I run when ANYTHING updates
})
But, we can optionally pass a dependency array as a second argument to tell React to only re-run the hook when the specified dependencies update:
useEffect(()=> {
// I only run when someValue updates
}, [someValue])
But what about if you have nested data, say an object containing form data, e.g.
const values = {
name: 'Aileen',
age: 26,
city: 'Edinburgh',
favoriteFood: 'pizza 🍕'
}
What if I want to trigger a side-effect when the user updates just their age, and not when any other value changes?
It seems obvious in hindsight, but you can watch for nested values changing simply by referencing the nested property with dot notation:
useEffect(()=> {
ageChangeSideEffect(values.age);
}, [values.age])
Additionally, we can trigger the useEffect()
hook for deeper nested objects if necessary:
useEffect(()=> {
// do something
}, [someValue.someNestedValue.someDeeplyNestedValue])
Top comments (4)
It's a fine solution if the object property always exists however if the property is not present at some point you get a reference error. My workaround in this scenario is to check if prop exists inside the hook
useEffect(()=> {
if (values?.age) {
ageChangeSideEffect(values.age);
}
}, [values])
I think is better to use values?.age as a dependency, to avoid to listen all changes in values.
There is no change listening in
values
because it's an object which is checked for equality by reference. Ifvalues
is passed to the component as a property and its value is composed as a plain inline object, it will be a new value on each render.Please un-learn what you learned "today":
github.com/facebook/react/issues/1...