参考文档
zustand的优势
相对其他状态管理工具,zustand具有以下优势:
- 较少样板代码
- Zustand仅在
state
发生更改时渲染组件。状态的更改通常可以在不必重新渲染组件的情况下进行处理。 - 状态管理是集中的,并通过简单定义的操作进行更新。在这方面,它与Redux类似,但与Redux不同,在Redux中,开发人员必须创建
reducer
、actions
和dispatch
来处理状态,Zustand使其变得更容易。 - 使用
Hooks
来消耗状态。Hooks
在React中很流行,因此也是一种受欢迎的状态管理方法。 - Zustand利用了易于使用和易于实现的代码。
- 通过消除使用
Context Provides
来提供干净的代码,从而产生更短、更可读的代码。
一、使用
1. 安装依赖
npm i zustand
2. 创建Store
zustand 提供了create
方法以创建store对象
。该store对象包含了我们项目中要用到的所有状态,以及操作这些状态的函数方法:
// src/zustandStore/countStore.js
import {create} from 'zustand';
const countStore = create(set => ({
count: 0, // 状态值
// 增加函数,通过传入的 state 获取当前state中的值,实现递增
increment: () => set(state => ({count: state.count + 1})),
// 减少函数,通过传入的 state 获取当前state中的值,实现递增
decrement: () => set(state => ({count: state.count - 1})),
}))
export default countStore;
如上,create
函数中有个 set()
方法,通过该方法,我们可以定义状态变更方法;
set()
中的state
形参可以让我们拿到当前状态值,并在该值的基础上进行操作(递增/递减等等);
3. 访问存储状态
创建 src/App.zustand.jsx
文件,在其中我们引入刚刚创建的 countStore
函数;
调用该函数,并解构出我们需要的 count
变量、increment
和decrement
两个操作方法:
import countStore from './zustandStore/countStore';
function App() {
// 导出count及两个操作方法
const {count, increment, decrement} = countStore();
return (
<div>
<button onClick={increment}>count ++</button>
{count}
<button onClick={decrement}>count --</button>
</div>
)
}
export default App;
在src/index.js
中引入 App
:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.zustand';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
4. 效果
三、异步获取数据
zustand中对于异步的支持不需要特殊的操作,直接在函数中编写异步逻辑,最后只需要调用set方法传入新状态
即可。
1. 编码
我们新建一个 src/zustandStore/channelStore.js
文件:
import { create } from 'zustand';
// 我这里使用axios 获取数据
import axios from 'axios';
const channelStore = create(set => ({
// 状态数据
channelList: [],
// 异步方法
fetchChannelList: async () => {
const res = await axios.get('http://geek.itheima.net/v1_0/channels');
set({
channelList: res.data.data.channels;
})
}
}))
export default channelStore;
在 src/App.zustand.jsx
文件 导入channelStore:
...
import {useEffect} from 'react';
import channelStore from './zustandStore/channelStore';
...
function App() {
const {channelList, fetchChannelList} = channelStore();
// useEffect 中调用异步操作
useEffect(() => {
fetchChannelList();
}, [fetchChannelList])
return (
...
<ul>
{channelList.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
...
)
}
2. 效果
四、切片组合
当我们项目较复杂,store较大时 可以使用 切片模式
将模块进行切分组合,类似于模块化:
经过上述操作,我们的 zustandStore
目录下应该有 channelStore.js
和 countStore.js
两个文件:
我们新建一个 zustandStore/index.js
:
import {create} from 'zustand';
import channelStore from './channelStore';
import countStore from './countStore';
// 组合组件
const zustandStore = create((...args) => {
return {
...channelStore(...args),
...countStore(...args)
}
})
export default zustandStore;
src/App.zustand.jsx
中做下调整:
// 切片模式
import zustandStore from './zustandStore';
...
// 切片模式
const {count, increment, decrement, channelList, fetchChannelList} = zustandStore();
...