-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add useShallow #2090
feat: add useShallow #2090
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 886bf51:
|
src/shallow.ts
Outdated
? (prev.current as U) | ||
: (prev.current = next) | ||
}, | ||
[selector] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need useMemo nor useCallback for this, because Zustand doesn't require stable selector.
Do you prefer useRef
? I think we should use useMemo like #1937 (reply in thread) , because React may prohibit updating ref during render in the future (L73 is usually not allowed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version 1 of #1937 (reply in thread) requires useCallback to use inline selectors.
Version 2 of #1937 (reply in thread) works but we open the door to potential stale closure issues.
If there are no better alternatives version 2 is better.
Are there less cumbersome alternatives?
I wish we could use useEvent or something similar during the render phase :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, that's my bad. I forgot about it. Let's use useRef
then.
I think you can remove useMemo from your implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not necessary because the caller of useShallow can always wrap the selector with useCallabck.
We never need useCallback, it doesn't improve anything.
import { create } from 'zustand'
import { useShallow } from 'zustand/shallow'
const useMyStore = create(() => ({ a: 1, b: 2, c: 3 }))
export const TestShallow = () => {
const output = useMyStore(useShallow(Object.keys))
return <div>{output.join(',')}</div>
} Maybe, |
export function useShallow<S, U>(selector: (state: S) => U): (state: S) => U { | ||
const prev = useRef<U>() | ||
|
||
return (state) => { | ||
const next = selector(state) | ||
return shallow(prev.current, next) | ||
? (prev.current as U) | ||
: (prev.current = next) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good to me.
I don't think we need that section. We need to update docs too. Would you like to work on this PR, or should it be a separate PR? |
I think it's because in the production mode.
Yeah, that should be the way to go. |
I'll open another PR tomorrow. Thanks EDIT: see #2090 (comment) |
Added guide in 9526d87. Let me know if it's ok. Thanks |
It's only mentioned in the readme ( I'll update it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on docs too!
Below are some comments.
readme.md
Outdated
@@ -86,36 +86,31 @@ const honey = useBearStore((state) => state.honey) | |||
|
|||
If you want to construct a single object with multiple state-picks inside, similar to redux's mapStateToProps, you can tell zustand that you want the object to be diffed shallowly by passing the `shallow` equality function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to revise this line too?
Co-authored-by: Daishi Kato <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for your contribution!
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [zustand](https://togithub.com/pmndrs/zustand) | [`4.4.1` -> `4.4.6`](https://renovatebot.com/diffs/npm/zustand/4.4.1/4.4.6) | [![age](https://developer.mend.io/api/mc/badges/age/npm/zustand/4.4.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/zustand/4.4.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/zustand/4.4.1/4.4.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/zustand/4.4.1/4.4.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>pmndrs/zustand (zustand)</summary> ### [`v4.4.6`](https://togithub.com/pmndrs/zustand/releases/tag/v4.4.6) [Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.4.5...v4.4.6) v4.4.5 has an issue with some TypeScript configs about module resolution. It should be fixed now. Thanks for the patience. #### What's Changed - Update export types by [@​dbritto-dev](https://togithub.com/dbritto-dev) in [https://github.com/pmndrs/zustand/pull/2170](https://togithub.com/pmndrs/zustand/pull/2170) #### New Contributors - [@​cheatkey](https://togithub.com/cheatkey) made their first contribution in [https://github.com/pmndrs/zustand/pull/2147](https://togithub.com/pmndrs/zustand/pull/2147) - [@​frixaco](https://togithub.com/frixaco) made their first contribution in [https://github.com/pmndrs/zustand/pull/2166](https://togithub.com/pmndrs/zustand/pull/2166) **Full Changelog**: pmndrs/zustand@v4.4.5...v4.4.6 ### [`v4.4.5`](https://togithub.com/pmndrs/zustand/releases/tag/v4.4.5) [Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.4.4...v4.4.5) Hopefully, it should fix some issues with Node.js environment including Next.js. #### What's Changed - fix: importing CJS React in ESM by [@​dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/2154](https://togithub.com/pmndrs/zustand/pull/2154) - Apply publint recommendations by [@​dbritto-dev](https://togithub.com/dbritto-dev) in [https://github.com/pmndrs/zustand/pull/2157](https://togithub.com/pmndrs/zustand/pull/2157) #### New Contributors - [@​plrs9816](https://togithub.com/plrs9816) made their first contribution in [https://github.com/pmndrs/zustand/pull/2137](https://togithub.com/pmndrs/zustand/pull/2137) - [@​Brammm](https://togithub.com/Brammm) made their first contribution in [https://github.com/pmndrs/zustand/pull/2139](https://togithub.com/pmndrs/zustand/pull/2139) - [@​sobies93](https://togithub.com/sobies93) made their first contribution in [https://github.com/pmndrs/zustand/pull/2142](https://togithub.com/pmndrs/zustand/pull/2142) **Full Changelog**: pmndrs/zustand@v4.4.4...v4.4.5 ### [`v4.4.4`](https://togithub.com/pmndrs/zustand/releases/tag/v4.4.4) [Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.4.3...v4.4.4) There was a tiny issue in v4.4.3, which broke with some bundlers, which this version fixes. #### What's Changed - fix(build): patch entry points zustand/shallow for CJS by [@​dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/2128](https://togithub.com/pmndrs/zustand/pull/2128) **Full Changelog**: pmndrs/zustand@v4.4.3...v4.4.4 ### [`v4.4.3`](https://togithub.com/pmndrs/zustand/releases/tag/v4.4.3) [Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.4.2...v4.4.3) The changes in v4.4.2 were troublesome for some users. This version should fix/mitigate such cases. #### What's Changed - fix(shallow): Extract shallow vanilla and react by [@​dbritto-dev](https://togithub.com/dbritto-dev) in [https://github.com/pmndrs/zustand/pull/2097](https://togithub.com/pmndrs/zustand/pull/2097) - fix(types): mitigate devtools typing by [@​dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/2099](https://togithub.com/pmndrs/zustand/pull/2099) **Full Changelog**: pmndrs/zustand@v4.4.2...v4.4.3 ### [`v4.4.2`](https://togithub.com/pmndrs/zustand/releases/tag/v4.4.2) [Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.4.1...v4.4.2) This adds `useShallow` hook to cover some use cases that are deprecated with v4.4.0 change. Check out [the guide](https://togithub.com/pmndrs/zustand/blob/ec538e9d4c0b9b5759e6dfd0fd3c9a21f8236949/docs/guides/prevent-rerenders-with-use-shallow.md). ##### Migration Guide [#​1991](https://togithub.com/pmndrs/zustand/issues/1991) requires something like below if you are using the `devtools` middleware *and* TypeScript. ```diff import { devtools } from 'zustand/middleware' + import type {} from '@​redux-devtools/extension' ``` ##### What's Changed - fix(types)(middleware/devtools): avoid copying types by [@​dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/1991](https://togithub.com/pmndrs/zustand/pull/1991) - fix(traditional): make defaultEqualityFn optional in TS Types by [@​charkour](https://togithub.com/charkour) in [https://github.com/pmndrs/zustand/pull/2060](https://togithub.com/pmndrs/zustand/pull/2060) - feat: add useShallow by [@​FaberVitale](https://togithub.com/FaberVitale) in [https://github.com/pmndrs/zustand/pull/2090](https://togithub.com/pmndrs/zustand/pull/2090) ##### New Contributors - [@​aykutkardas](https://togithub.com/aykutkardas) made their first contribution in [https://github.com/pmndrs/zustand/pull/1993](https://togithub.com/pmndrs/zustand/pull/1993) - [@​michelts](https://togithub.com/michelts) made their first contribution in [https://github.com/pmndrs/zustand/pull/1997](https://togithub.com/pmndrs/zustand/pull/1997) - [@​elusive](https://togithub.com/elusive) made their first contribution in [https://github.com/pmndrs/zustand/pull/2001](https://togithub.com/pmndrs/zustand/pull/2001) - [@​mayank1513](https://togithub.com/mayank1513) made their first contribution in [https://github.com/pmndrs/zustand/pull/2015](https://togithub.com/pmndrs/zustand/pull/2015) - [@​fdb](https://togithub.com/fdb) made their first contribution in [https://github.com/pmndrs/zustand/pull/2029](https://togithub.com/pmndrs/zustand/pull/2029) - [@​tmkx](https://togithub.com/tmkx) made their first contribution in [https://github.com/pmndrs/zustand/pull/2032](https://togithub.com/pmndrs/zustand/pull/2032) - [@​OshriAsulin](https://togithub.com/OshriAsulin) made their first contribution in [https://github.com/pmndrs/zustand/pull/2028](https://togithub.com/pmndrs/zustand/pull/2028) - [@​ivanquirino](https://togithub.com/ivanquirino) made their first contribution in [https://github.com/pmndrs/zustand/pull/2047](https://togithub.com/pmndrs/zustand/pull/2047) - [@​stavkamil](https://togithub.com/stavkamil) made their first contribution in [https://github.com/pmndrs/zustand/pull/2071](https://togithub.com/pmndrs/zustand/pull/2071) - [@​NaamuKim](https://togithub.com/NaamuKim) made their first contribution in [https://github.com/pmndrs/zustand/pull/2088](https://togithub.com/pmndrs/zustand/pull/2088) - [@​FaberVitale](https://togithub.com/FaberVitale) made their first contribution in [https://github.com/pmndrs/zustand/pull/2090](https://togithub.com/pmndrs/zustand/pull/2090) **Full Changelog**: pmndrs/zustand@v4.4.1...v4.4.2 </details> --- ### Configuration 📅 **Schedule**: Branch creation - "after 4pm every weekday" in timezone Europe/Paris, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/specfy/specfy). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40Ni4wIiwidXBkYXRlZEluVmVyIjoiMzcuNDYuMCIsInRhcmdldEJyYW5jaCI6ImNob3JlL3Jlbm92YXRlQmFzZUJyYW5jaCJ9--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
* feat: add useShallow See - pmndrs/zustand#1937 - pmndrs/zustand#1937 (reply in thread) - pmndrs/zustand#1937 (reply in thread) * chore(useShallow): improve unit tests * chore(useShallow): PR feedback pmndrs/zustand#2090 (comment) * fix(useShallow): tests not working on test_matrix (cjs, production, CI-MATRIX-NOSKIP) * chore(useShallow): fix eslint warning issue (unused import) * refactor(useShallow): simplify tests * docs(useShallow): add guide * fix(useShallow): prettier:ci error https://github.com/pmndrs/zustand/actions/runs/6369420511/job/17289749161?pr=2090 * docs(useShallow): update readme * docs(useShallow): remove obsolete line from readme Co-authored-by: Daishi Kato <[email protected]> * doc(useShallow): PR feedback pmndrs/zustand#2090 (comment) * docs(useShallow): small improvements of the useShallow guide --------- Co-authored-by: Daishi Kato <[email protected]>
Summary
Adds a
useShallow
hook to prevent unnecessary re-renders when a selector outputs the same value according to shallow equal.Basic usage
See tests in
shallow.test.tsx
for more details.Related Issues or Discussions
Check List
yarn run prettier
for formatting code and docs