🧊 feat(hooks): add useCustomCompareEffect - #508
Open
ashenoooone wants to merge 2 commits into
Open
Conversation
…areEffect и useDeepEffect
…равнением на useCompareEffect useCompareEffect(effect, deps, compare?) применяет compare к каждой зависимости отдельно, по умолчанию deepEqual. На уровне всего списка shallowEqual сравнивал бы зависимости по ссылке, то есть вёл бы себя как обычный useEffect. BREAKING CHANGE: useShallowEffect удалён. Миграция — useCompareEffect(fn, deps, shallowEqual), но поведение меняется: старый хук вопреки названию сравнивал рекурсивно. Для прежней семантики третий аргумент не передавать.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #507
useCompareEffect(effect, deps, compare?)runs the effect when the compare function says a dependency changed, instead of relying on React's reference check.comparedefaults todeepEqual.The compare function returns
truewhen the values are equal and the effect is skipped. It is applied to each dependency separately, not to the list as a whole — applied to the whole list,shallowEqualwould compare each dependency by reference and behave exactly like a plainuseEffect.It is read fresh on every render, so it does not belong in
deps. On mount the effect always runs and the compare function is not called at all, so it never has to handle an undefined previous value. Without dependencies the hook keeps theuseEffect(fn)meaning and runs on every render.Changes are tracked with a counter, and
useEffectreceives[signalRef.current], never the caller's array. So a dependency list that changes length never triggers React'schanged size between renderswarning, and React's ownObject.iscannot overrule the compare function:deepEqualmoved out ofuseShallowEffect.tsintopackages/core/src/helpers/deepEqual, next to a newshallowEqual. The move fixes what the old implementation got wrong:NaNwas not equal to itself, any twoDates compared equal,Set,Mapand symbol keys were unhandled, a cyclic dependency overflowed the stack, and the key loop was quadratic on wide objects. Two rules are deliberate and documented in the JSDoc: Set members and Map keys compare by reference while Map values compare deeply; and an object with no own enumerable string keys that is not a plain object compares by reference, soError,URL,ArrayBufferand DOM nodes do not all come out equal.Breaking changes
useShallowEffectis removed — with the comparison as an argument, a hook per comparison rule is redundant. The migration isuseCompareEffect(fn, deps, shallowEqual), and it is not behavior-preserving: the old hook compared recursively despite its name, so callers who relied on that drop the third argument instead.The exported
deepEqualalso keeps its name with different semantics. Both need a line in the release notes, otherwise they look like a regression appearing with no change on the caller's side.52 tests cover this, including the case where shallow and deep disagree.