Reputation: 570
I am wondering if there is a better way to achieve the same thing as below. This code works but it forces this useEffect to mount and un-mount a few times before it can make it through the if statement, which is not ideal.
I have a useEffect like below...
useEffect(() => {
console.log("setNames mounted")
if (devices !== null && deviceNames !== null){
setNames(trueDeviceNames(devices.devices, deviceNames.values))
}
return ()=> {
console.log("setNames un-mounted")
}
}, [devices, deviceNames])
I have 2 other useEffects that fetch data and setDevices and setDeviceNames. I don't want to run THIS useEffect until they have completed their fetches and are no longer null. My code works but surely there is a cleaner way to achieve this?
Upvotes: 1
Views: 80
Reputation: 2341
useEffect mount and unmount is on the half of [devices, deviceNames]
shallow comparison, so the function call is caused by the change of devices or deviceNames. you may want to consider those values for optimizing your useEffects.
your useEffect will not cause your component re-render until both devices are deviceNames are in-equal to null.
Note Shallow comparison use reference check for objects ant will pass true every time they change.
e.g.
shallowEqual({value: '1'}, {value: 1}) // false
shallowEqual({value: 1}, {value: 1}) // false
shallowEqual({value:'1'}, {value: '1'}) // false
shallowEqual('1', '1') // true
shallowEqual(1, 1}) // true
shallowEqual('1', 1) // false '1' !== 1
so you can optimize your useEffect by more precise dependencies array
useEffect(() => {
console.log("setNames mounted")
if (devices !== null && deviceNames !== null){
setNames(trueDeviceNames(devices.devices, deviceNames.values))
}
return ()=> {
console.log("setNames un-mounted")
}
}, [devices && devices.devices, deviceNames && deviceNames.values])
or if you are sure that devices and deviceNames are callable you can write the cleaner version
[devices.devices, deviceNames.values])
These will only update by exact value change and prevent lots of re-renders
If you want to call useEffect only on both value existence you can add dependencies like following
[Boolean(devices) && Boolean(deviceNames)]
this will be false until both have truthy value and call useEffect at most 2 times on startup scenario
Upvotes: 1