-
This can be controversial, but let's go. MotivationA part of Zustand philosophy is being small, crazy small. Supporting custom While the primary recommendation is not specifying ProposalWe deprecate specifying We provide new MigrationIf you don't use If you always use - import { create } from 'zustand'
+ import { createWithEqualityFn } from 'zustand/traditional'
import { shallow } from 'zustand/shallow'
- const useFooStore = create(...)
+ const useFooStore = createWithEqualityFn(..., shallow)
// in a component
- const { ... } = useFooStore(..., shallow)
+ const { ... } = useFooStore(...) You can use - import { create } from 'zustand'
+ import { createWithEqualityFn } from 'zustand/traditional'
- const useFooStore = create(...)
+ const useFooStore = createWithEqualityFn(..., Object.is) // or deepEqual here
// in a component
const { ... } = useFooStore(..., deepEqual) BenefitsFrom the library perspective, we can make For users who use Drawbacks
Some people have to migrate, but we are not sure how many people there are. (We assume it's relatively minor.)
AlternativesWe could simply drop
|
Beta Was this translation helpful? Give feedback.
Replies: 25 comments 130 replies
-
How about this?
Importing "zustand/shallow" to use a custom equality function, and not actually using "shallow" is counter-intuitive, doesn't feel like a good choice. Or maybe
|
Beta Was this translation helpful? Give feedback.
-
#1945 is open. |
Beta Was this translation helpful? Give feedback.
-
While I like this change, I'm a bit confused about this being a breaking change. Shouldn't this have been a new major update instead of a minor bump? @dai-shi |
Beta Was this translation helpful? Give feedback.
-
Hey guys, what about this pattern? // Mimic the hook returned by `create`
import { useContext } from 'react'
import { useStore } from 'zustand'
function useBearContext<T>(
selector: (state: BearState) => T,
equalityFn?: (left: T, right: T) => boolean
): T {
const store = useContext(BearContext)
if (!store) throw new Error('Missing BearContext.Provider in the tree')
return useStore(store, selector, equalityFn)
} From: https://docs.pmnd.rs/zustand/guides/initialize-state-with-props I have this pattern throughout my project and when updating to the latest version of zustand, it tells me that the useStore is deprecated and gives a compilation error, it tells me to import useStoreWithEqualityFn, but when doing the project build, the console tells me this: [DEPRECATED] Use |
Beta Was this translation helpful? Give feedback.
-
hi @dai-shi, can you please give an example how to use import { create } from 'zustand';
import { shallow } from 'zustand/shallow';
const store = create(...)
const foo = store(someSelector, shallow); Thank you ❤️ |
Beta Was this translation helpful? Give feedback.
-
Hi @dai-shi, I got this error when using createWithEqualityFn + devtools the code is like this const store = createWithEqualityFn<Store>(devtools((set) => {
...
}), shallow); the error is like this
|
Beta Was this translation helpful? Give feedback.
-
How should we use this when building our store with slices? I tried with the following, but still get the deprecated warning: Example slice: import { StateCreator } from "zustand"
export type UISliceType = typeof initialState & {
ui: {
setDarkMode: (dark: boolean) => void
setMobileMenuOpen: (mobileMenuOpen: boolean) => void
setSearchOpen: (searchOpen: boolean) => void
}
}
export const initialState = {
ui: {
dark: false,
mobileMenuOpen: false,
searchOpen: false,
},
}
const createUISlice: StateCreator<UISliceType, [], []> = (set) => ({
ui: {
...initialState.ui,
setDarkMode: (dark) => set((state) => ({ ui: { ...state.ui, dark } })),
setMobileMenuOpen: (mobileMenuOpen) =>
set((state) => ({ ui: { ...state.ui, mobileMenuOpen } })),
setSearchOpen: (searchOpen) =>
set((state) => ({ ui: { ...state.ui, searchOpen } })),
},
})
export default createUISlice Example create function: export const createClientStore = (initialState?: initialStateType) => {
return createWithEqualityFn<SlicesType>()((...a) => ({
...createAlertSlice(...a),
...createAuthSlice(initialState?.auth)(...a),
...createCartSlice(initialState?.cart)(...a),
...createShopSlice(...a),
...createUISlice(...a),
}), shallow)
} |
Beta Was this translation helpful? Give feedback.
-
This breaks for context usage like |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I never use create with an equality function across all my stores (but often and selectively use shallow comparisons) - and my app outputs this to the console in production. I'm not sure I'm getting the warning messages because of the v5 transition, rather this seems like a false positive. |
Beta Was this translation helpful? Give feedback.
-
Hi @dai-shi - First, thank you for all your efforts with this library, it is much appreciated! Would it be possible to have this warning shown only one time? It is currently logging on every interaction with my app and clogging up my console during dev, making it hard to view other issues or log values to the console. Screencast.from.06-08-23.00.36.51.webmHappy to open a PR if this is an accepted suggestion. |
Beta Was this translation helpful? Give feedback.
-
I Just open a issue to track the migration : #1982 |
Beta Was this translation helpful? Give feedback.
-
I'm a bit confused. Part of our workflow is to use Zustand to avoid prop drilling. As a result we create selectors that create arrays, and then we use const [propA, propB] = useMyStore(state => [state.propA, state.propB], shallow) We use this pattern everywhere, and it's generally understood why this pattern exists. Why is this changing now in a minor version? Is the v5 version going to do a const propA = useMyStore(state => state.propA)
const propB = useMyStore(state => state.propB) This will be the second big change that will require us to rework large portions of our code (the first being the |
Beta Was this translation helpful? Give feedback.
-
@arvinxx I think you need - export { useStore } from 'zustand';
+ export { useStoreWithEqualityFn as useStore } from 'zustand/traditional'; Thanks for reporting this. I wasn't aware that it affects mocking. Any suggestion to improve docs for others? |
Beta Was this translation helpful? Give feedback.
-
Hey @dai-shi love all the work you guys have done with Zustand, it is my go-to library for state management 🧸. I'm dropping by to ask if it is possible to update the docs on how to create a store, some people on my team got confused as their console got the deprecated warning, we are updating our docs as well. It should be Thank you again for this awesome work! |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Hi, How can I get rid of all these warnings, not even using Zustand? Using Versions:
Many thanks! |
Beta Was this translation helpful? Give feedback.
-
This update makes me trust NPM package updates even less. I cannot update this package, if I do not want to spend 30+ minutes of figuring out how to update my code. |
Beta Was this translation helpful? Give feedback.
-
I tried migrating to |
Beta Was this translation helpful? Give feedback.
-
First of all, thanks for that amazing library. I think this upgrade does the opposite of its intention, it adds complexity. Zustand is appreciated mainly I think because it's dead simple to use in all edge cases. One way to solve every frustrating part of global state management. It's satisfying to not have to think about which special import to use for the store factory based on what one intends to do in the future (shallow comparaison or not, locally or globally). I do not think that the gain in code size justifies this, it just feels wrong and over-engineered. This is of course just my opinion. I've read the full thread, the argument that it will help people who complained about having to specify "shallow" every time seems weird. One can always create a shared one-line custom hook that wraps |
Beta Was this translation helpful? Give feedback.
-
I use shallow frequently to create computed / derived state within a hook e.g. here where I only want an render when the keys in an object ( const objects = useObjects((state) => Object.keys(state.objects), shallow); It surprised me to see this pattern which is prominently part of the documentation be demoted like this. Why is it that shallow comparison is not possible without |
Beta Was this translation helpful? Give feedback.
-
Not a fan of tying the equality function to the store. Whether to use I also create selectors outside react, so maybe add something like a |
Beta Was this translation helpful? Give feedback.
-
is it correct? 👀 zustand-v4 const [
isLoaded,
isLoading,
posts,
pagination,
updateAt,
fetchNext,
reset,
] = usePageCache(state => {
const cache = state.caches[cacheKey] || {}
return [
cache.isLoaded,
cache.isLoading,
cache.posts,
cache.pagination,
cache.updateAt,
state.fetchNext,
state.reset,
]
}, shallow) zustand-v5 const [
isLoaded,
isLoading,
posts,
pagination,
updateAt,
fetchNext,
reset,
] = usePageCache(
useShallow(
state => {
const cache = state.caches[cacheKey] || {}
return [
cache.isLoaded,
cache.isLoading,
cache.posts,
cache.pagination,
cache.updateAt,
state.fetchNext,
state.reset,
]
}
)
) |
Beta Was this translation helpful? Give feedback.
-
I'm sorry for my ignorance here, but in the initial message you said :
However, I'm not sure what is the Does the following code use import { create } from 'zustand';
const useBearStore = create(set => ({
count: 0,
addBear: () => set(state => ({
count: state.count + 1
})),
}));
function BearCounter() {
const addBear = useBearStore(state => state.addBear);
const count = useBearStore(state => state.count);
return ...
} Thanks! |
Beta Was this translation helpful? Give feedback.
-
With React 18, |
Beta Was this translation helpful? Give feedback.
#1945 is open.