45

A page displays a list of objects [{name:, age:}, ...] A second page allows to update the name of a particular object. Then using hooks, how should I implement useEffect() so the list on the front page updates only when a name change has been detected?

const [objects, setObjects] = useState([]);

useEffect(()=> {
  getAllObjects()
},[getAllObjects, objects]);
1

5 Answers 5

38

Instead of passing the entire object to the dependency array, make sure that you only pass name. Which you can do by returning the names

const [objects, setObjects] = useState([])

useEffect(()=> {
      getAllObjects()
}, [getAllObjects, ...objects.map(item => item.name)])
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks, I am glad I asked I wouldnt have figured this trick out myself. Is it considered best practice though? The create-react-app linter raises a warning: React Hook useEffect has a spread element in its dependency array. This means we can't statically verify whether you've passed the correct dependencies. Do you know if I can get rid of it without disabling the linting ?
Maybe use objects.map(item => item.name).concat([getAllObjects]) for dependency array
Ok thanks, I tried... the linter then complained the expression is too complex and I should extract it to a variable... what I did and then pass the variable to the deps array... now it's telling me that the variable is a unnecessary dep... there might be a flaw in my design here...
In my case, I needed an object, ended up with: ...Object.keys(myObj).map(key => myObj[key])
@keif, an alternative to extract object values: ...Object.values(myObj)
|
7

Check https://dev.to/aileenr/til-you-can-watch-for-nested-properties-changing-in-react-s-useeffect-hook-26nj

One can just do:

useEffect(()=> {
      // do something
}, [values.name])

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. A workaround in this scenario is to check if prop exists inside the hook

useEffect(()=> {
    if (values?.name) {
        // do something
    }
}, [values])

1 Comment

the question was how to declare dependency to a property in an array/collection... (ie. in ember.js you would do it like [email protected])
5
// using JSON.stringify(object)
useEffect(() => {
   // your code here...
}, [JSON.stringify(dependencyObject)]);

The best solution is to use JSON.stringify(object) as it won't lead to any error on the initial load or warning about the changes in size of dependency variables.


// using spread operator
useEffect(() => {
   // your code here...
}, [ ...Object.values(dependencyObject) ]);

The solution with spread operator on object keys and values will cause an error if the object is null/undefined in the initial load.

/* 
  Also if you make a custom function that either returns the 
  values or empty array then React will give a warning about 
  the size change in dependency array.
*/
const getDependencies = (addressType: Address) => {
if (addressType) {
  return Object.values(addressType);
}
return [];
}

useEffect(() => {
   // your code here...
}, [ ...getDependencies(dependencyObject) ]);

So use JSON.stringyfy(object). it won't give any errors when the object is undefined or null and React won't complain about the change in size of dependency variables.

1 Comment

which is more efficient if the object will never be null?
1

None of the previous answers worked for me

This is my solution:

const [objects, setObjects] = useState([]);

useEffect(()=> {
  getAllObjects()
},[getAllObjects, ...Object.values(objects)]);

This way you are extracting the values from your state and once any of these values change the useEffect will be triggered

Comments

-5

Please add JSON.stringify for the nested object.

useEffect(()=> {
   getAllObjects()
},[getAllObjects, JSON.stringify(objects)]);

1 Comment

dependency array accepts variables not values

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.