React compares dependencies with Object.is, so an object or an array rebuilt during
render always counts as changed and the effect fires on every render. Filter objects,
option bags, query params: anything built inline hits this.
The library has one hook for that, useShallowEffect, and it does not do what its name
says. Its comparator recurses into nested values, so it is a deep compare. There is no
shallow compare, no honestly named deep one, and no way to pass your own rule for cases
where neither fits, like re-running only when user.id changes.
Proposed: useCustomCompareEffect(effect, deps, comparator) as the base hook, with
useShallowEffect and useDeepEffect as one-line wrappers over it, so the dependency
bookkeeping lives in one place. The two comparison functions become public helpers.
useCustomCompareEffect(() => subscribe(user), [user], ([user], [prev]) => user.id === prev.id);
useShallowEffect(() => console.log('effect'), [filter]);
useDeepEffect(() => console.log('effect'), [filter]);
Fixing useShallowEffect changes its behavior, so it needs a release note.
React compares dependencies with
Object.is, so an object or an array rebuilt duringrender always counts as changed and the effect fires on every render. Filter objects,
option bags, query params: anything built inline hits this.
The library has one hook for that,
useShallowEffect, and it does not do what its namesays. Its comparator recurses into nested values, so it is a deep compare. There is no
shallow compare, no honestly named deep one, and no way to pass your own rule for cases
where neither fits, like re-running only when
user.idchanges.Proposed:
useCustomCompareEffect(effect, deps, comparator)as the base hook, withuseShallowEffectanduseDeepEffectas one-line wrappers over it, so the dependencybookkeeping lives in one place. The two comparison functions become public helpers.
Fixing
useShallowEffectchanges its behavior, so it needs a release note.