夫唯不争,故天下莫能与之|

Halory

园龄:1个月粉丝:0关注:0

2025-02-06 15:21阅读: 23评论: 0推荐: 0

Zustand上手案例

image

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
posted @   Halory  阅读(23)  评论(0编辑  收藏  举报
(评论功能已被禁用)
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开