比较
比较
Zustand如何与类似的库相比较?
Zustand是React的众多状态管理库之一。在这个页面上,我们将讨论Zustand与其中一些库,包括Redux、Valtio、Jotai和Recoil的比较。
每个库都有其自身的优点和缺点,我们将比较每个库之间的关键差异和相似之处。
Redux
状态模型 (vs Redux)
从概念上讲,Zustand 和 Redux 非常相似,它们都基于不可变状态模型。然而,Redux 需要将应用程序包裹在上下文提供者中;Zustand 则不需要。
Zustand
import { create } from 'zustand'
type State = { count: number}
type Actions = { increment: (qty: number) => void decrement: (qty: number) => void}
const useCountStore = create<State & Actions>((set) => ({ count: 0, increment: (qty: number) => set((state) => ({ count: state.count + qty })), decrement: (qty: number) => set((state) => ({ count: state.count - qty })),}))
import { create } from 'zustand'
type State = { count: number}
type Actions = { increment: (qty: number) => void decrement: (qty: number) => void}
type Action = { type: keyof Actions qty: number}
const countReducer = (state: State, action: Action) => { switch (action.type) { case 'increment': return { count: state.count + action.qty } case 'decrement': return { count: state.count - action.qty } default: return state }}
const useCountStore = create<State & Actions>((set) => ({ count: 0, dispatch: (action: Action) => set((state) => countReducer(state, action)),}))
Redux
import { createStore } from 'redux'import { useSelector, useDispatch } from 'react-redux'
type State = { count: number}
type Action = { type: 'increment' | 'decrement' qty: number}
const countReducer = (state: State, action: Action) => { switch (action.type) { case 'increment': return { count: state.count + action.qty } case 'decrement': return { count: state.count - action.qty } default: return state }}
const countStore = createStore(countReducer)
import { createSlice, configureStore } from '@reduxjs/toolkit'
const countSlice = createSlice({ name: 'count', initialState: { value: 0 }, reducers: { incremented: (state, qty: number) => { // Redux Toolkit does not mutate the state, it uses the Immer library // behind scenes, allowing us to have something called "draft state". state.value += qty }, decremented: (state, qty: number) => { state.value -= qty }, },})
const countStore = configureStore({ reducer: countSlice.reducer })
渲染优化(对比 Redux)
在应用程序的渲染优化方面,Zustand 和 Redux 之间的处理方法没有太大区别。在这两个库中,都建议通过使用选择器手动应用渲染优化。
Zustand
import { create } from 'zustand'
type State = { count: number}
type Actions = { increment: (qty: number) => void decrement: (qty: number) => void}
const useCountStore = create<State & Actions>((set) => ({ count: 0, increment: (qty: number) => set((state) => ({ count: state.count + qty })), decrement: (qty: number) => set((state) => ({ count: state.count - qty })),}))
const Component = () => { const count = useCountStore((state) => state.count) const increment = useCountStore((state) => state.increment) const decrement = useCountStore((state) => state.decrement) // ...}
Redux
import { createStore } from 'redux'import { useSelector, useDispatch } from 'react-redux'
type State = { count: number}
type Action = { type: 'increment' | 'decrement' qty: number}
const countReducer = (state: State, action: Action) => { switch (action.type) { case 'increment': return { count: state.count + action.qty } case 'decrement': return { count: state.count - action.qty } default: return state }}
const countStore = createStore(countReducer)
const Component = () => { const count = useSelector((state) => state.count) const dispatch = useDispatch() // ...}
import { useSelector } from 'react-redux'import type { TypedUseSelectorHook } from 'react-redux'import { createSlice, configureStore } from '@reduxjs/toolkit'
const countSlice = createSlice({ name: 'count', initialState: { value: 0 }, reducers: { incremented: (state, qty: number) => { // Redux Toolkit does not mutate the state, it uses the Immer library // behind scenes, allowing us to have something called "draft state". state.value += qty }, decremented: (state, qty: number) => { state.value -= qty }, },})
const countStore = configureStore({ reducer: countSlice.reducer })
const useAppSelector: TypedUseSelectorHook<typeof countStore.getState> = useSelector
const useAppDispatch: () => typeof countStore.dispatch = useDispatch
const Component = () => { const count = useAppSelector((state) => state.count.value) const dispatch = useAppDispatch() // ...}
Valtio
状态模型 (vs Valtio)
Zustand 和 Valtio 在状态管理上采用了根本不同的方法。Zustand 基于不可变状态模型,而 Valtio 基于可变状态模型。
Zustand
import { create } from 'zustand'
type State = { obj: { count: number }}
const store = create<State>(() => ({ obj: { count: 0 } }))
store.setState((prev) => ({ obj: { count: prev.obj.count + 1 } }))
Valtio
import { proxy } from 'valtio'
const state = proxy({ obj: { count: 0 } })
state.obj.count += 1
渲染优化(对比 Valtio)
Zustand 和 Valtio 之间的另一个区别是,Valtio 通过属性访问进行渲染优化。然而,对于 Zustand,建议通过使用选择器手动应用渲染优化。
Zustand
import { create } from 'zustand'
type State = { count: number}
const useCountStore = create<State>(() => ({ count: 0,}))
const Component = () => { const count = useCountStore((state) => state.count) // ...}
Valtio
import { proxy, useSnapshot } from 'valtio'
const state = proxy({ count: 0,})
const Component = () => { const { count } = useSnapshot(state) // ...}
Jotai
状态模型 (vs Jotai)
Zustand 和 Jotai 之间有两个主要区别。首先,Zustand 是一个单一的存储,而 Jotai 由可以组合在一起的原子组成。其次,Zustand 存储是一个外部存储,这使得它在需要在 React 之外进行访问时更为适用。
Zustand
import { create } from 'zustand'
type State = { count: number}
type Actions = { updateCount: ( countCallback: (count: State['count']) => State['count'], ) => void}
const useCountStore = create<State & Actions>((set) => ({ count: 0, updateCount: (countCallback) => set((state) => ({ count: countCallback(state.count) })),}))
Jotai
import { atom } from 'jotai'
const countAtom = atom<number>(0)
渲染优化(对比 Jotai)
Jotai 通过原子依赖实现渲染优化。然而,对于 Zustand,建议通过使用选择器手动应用渲染优化。
Zustand
import { create } from 'zustand'
type State = { count: number}
type Actions = { updateCount: ( countCallback: (count: State['count']) => State['count'], ) => void}
const useCountStore = create<State & Actions>((set) => ({ count: 0, updateCount: (countCallback) => set((state) => ({ count: countCallback(state.count) })),}))
const Component = () => { const count = useCountStore((state) => state.count) const updateCount = useCountStore((state) => state.updateCount) // ...}
Jotai
import { atom, useAtom } from 'jotai'
const countAtom = atom<number>(0)
const Component = () => { const [count, updateCount] = useAtom(countAtom) // ...}
Recoil
状态模型 (vs Recoil)
Zustand 和 Recoil 之间的区别类似于 Zustand 和 Jotai 之间的区别。Recoil 依赖于原子字符串键,而不是原子对象引用标识。此外,Recoil 需要将应用程序包裹在上下文提供者中。
Zustand
import { create } from 'zustand'
type State = { count: number}
type Actions = { setCount: (countCallback: (count: State['count']) => State['count']) => void}
const useCountStore = create<State & Actions>((set) => ({ count: 0, setCount: (countCallback) => set((state) => ({ count: countCallback(state.count) })),}))
Recoil
import { atom } from 'recoil'
const count = atom({ key: 'count', default: 0,})
渲染优化(对比 Recoil)
与之前的优化比较类似,Recoil 通过原子依赖实现渲染优化。而在 Zustand 中,建议您通过使用选择器手动应用渲染优化。
Zustand
import { create } from 'zustand'
type State = { count: number}
type Actions = { setCount: (countCallback: (count: State['count']) => State['count']) => void}
const useCountStore = create<State & Actions>((set) => ({ count: 0, setCount: (countCallback) => set((state) => ({ count: countCallback(state.count) })),}))
const Component = () => { const count = useCountStore((state) => state.count) const setCount = useCountStore((state) => state.setCount) // ...}
Recoil
import { atom, useRecoilState } from 'recoil'
const countAtom = atom({ key: 'count', default: 0,})
const Component = () => { const [count, setCount] = useRecoilState(countAtom) // ...}