Zustand上手案例

zustand
zustand是一个极简的状态管理工具,可以用于替代redux
npm i zustand
示例
下面是一个示例代码,利用zustand实现计数功能:
import { create } from 'zustand'
// 创建store
const useStore = create((set) => {
    return {
        // 状态变量
        count: 0,
        
        // 修改状态变量的函数
        inc: () => {
            // 基于原数据进行修改(需要传入state)
            set((state) => ({
                count: state.count + 1
            }))
            
            // 直接修改
            set({ count: 100 })
        }
    }
})
// 将store绑定到组件上
function App () {
    const { count, inc } = useStore()
    return (
    <button onClick={inc}>{ count }</button>
    )
}
异步支持
可以直接在store里面编写异步函数:
import { create } from 'zustand'
// 创建store
const useStore = create((set) => {
    return {
        // 状态变量
        info: {}
        id: {}
        
        // 获取用户信息
        fetchInfo: async () => {
            const res = await fetchInfoApi(id)
            set({
                info: res.data.data
            })
        }
    }
})
切片模式
我们可以在一个文件里面写多个store,最后将这些store组合导出:
import { create } from 'zustand'
// 创建用户切片
const createUserStore = (set) => {
    return {
        ...
    }
}
    
    
// 创建班级切片
const createClassStore = (set) => {
    return {
        ...
    }
}
    
// 组合切片
const useStore = create((...a) => ({
    ...createUserStore(...a),
    ...createClassStore(...a)
}))
// 组件使用
function App () {
    // 解构获取
    const { count, inc } = useStore()
    return (
    <button onClick={inc}>{ count }</button>
    )
}
用户信息存储实例
下面的zustand是我的某一项目中的实际代码,用户登录成功后,后端会返回用户登录的token,使用store中的setToken()方法进行持久化,并且存储方式设置为localStorage。此时在配置axios拦截器时就可以通过调用本地存储获取token。
登录成功的同时,可以立即发送获取用户信息的请求,并将得到的用户信息通过setUserInfo(),以此持久化用户的信息。
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
const createUserStore = create(
  persist(
    set => ({
      token: '',
      userInfo: {},
      setToken: value => set({ token: value }),
      setUserInfo: value => set({ userInfo: value }),
    }),
    {
      name: 'reserve_user_store',
      getStorage: () => localStorage,
    }
  )
)
export default createUserStore
antd实现暗黑/明亮模式切换
对于antd中的主题切换,使用zustand管理当前的主题配置也非常方便。其中mode用于模式的判断,bgImg用于设置匹配当前模式的背景图片,toggle()用于模式的切换,并且保存当前的主题信息。下面是具体的store配置。
import { create } from 'zustand'
const createThemeStore = create(set => {
  return {
    mode: localStorage.getItem('lab_theme') === 'light' ? 'light' : 'dark',
    bgImg:
      localStorage.getItem('lab_theme') === 'light'
        ? 'https://xxx.xxx/light.jpg'
        : 'https://xxx.xxx/dark.jpg',
    toggle: mode => {
      set(() => ({
        mode: mode === 'light' ? 'light' : 'dark',
        bgImg:
          mode === 'light'
            ? 'https://xxx.xxx/light.jpg'
            : 'https://xxx.xxx/dark.jpg',
      }))
    },
  }
})
export default createThemeStore
在实际的页面中,我一般这样使用:
// 主题切换按钮单独封装成一个组件
// ThemeToggle.jsx
import createThemeStore from '@/store/theme'
import { Button } from 'antd'
import { useEffect } from 'react'
import { MoonFilled, SunFilled } from '@ant-design/icons'
export default function ThemeToggle() {
  const { mode, toggle } = createThemeStore()
  useEffect(() => {
    const lab_theme = localStorage.getItem('lab_theme', null)
    if (lab_theme === null) {
      if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
        localStorage.setItem('lab_theme', 'dark')
        toggle('dark')
      } else {
        localStorage.setItem('lab_theme', 'light')
        toggle('light')
      }
    }
  }, [toggle])
  const modeChange = () => {
    if (mode === 'light') {
      localStorage.setItem('lab_theme', 'dark')
      toggle('dark')
    } else {
      localStorage.setItem('lab_theme', 'light')
      toggle('light')
    }
  }
  return (
    <Button
      onClick={modeChange}
      type='text'
      icon={mode === 'dark' ? <MoonFilled /> : <SunFilled />}
      style={{
        fontSize: '16px',
        width: 64,
        height: 64,
        border: 'none',
      }}
    />
  )
}
// 主页面
// App.jsx
import {
    Button,
    ConfigProvider,
    theme,
} from 'antd'
import createThemeStore from '@/store/theme'
import ThemeToggle from '@/components/ThemeToggle'
const App = () => {
    const { mode, bgImg } = createThemeStore()
    return (
        <div style={{
                background: `center/cover url(${bgImg})`
            }}>
            <ConfigProvider
                theme={{
                    algorithm:
                    mode === 'light' ? theme.defaultAlgorithm : theme.darkAlgorithm,
                }}
                >
                <ThemeToggle />
            </ConfigProvider>
        </div>
    )
}
export default App

        zustand在React中的使用
    
                
            
        
浙公网安备 33010602011771号