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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步