将 Zusand 与 React JS 结合使用!🚀
在现代 React JS 应用程序中,状态管理是必不可少的。因此,今天我将向您介绍“ Zustand ”,一个管理应用程序状态的流行替代方案。
欢迎任何形式的反馈,谢谢,希望您喜欢这篇文章。🤗
🚨 注意:本文要求您了解React 和 TypeScript的基础知识。
目录。
📌结论。
🚀 Zusand 是什么?
Zusand 是一个小型、快速且可扩展的状态管理解决方案。它的状态管理是集中式的、基于操作的。
Zusand 由 Jotai 和 React-spring 的创建者开发。
您可以在 React 和其他一些技术(如 Angular、Vue JS 甚至原始 JavaScript)中使用 Zustand。
Zusand 是其他状态管理器(如 Redux、Jotai Recoil 等)的替代品。
⭕ 使用 Zusand 的优势。
- 重复代码更少(与 Redux 相比)。
- 易于理解的文档。
- 灵活性
- 您可以以简单的方式使用 Zustand,使用 TypeScript,您可以集成 immer 以实现不变性,甚至可以编写类似于 Redux 模式(reducers 和 dispatch)的代码。
- 它不会像 Redux 中常见的那样将应用程序包装在提供程序中。
- 仅当发生变化时才渲染组件。
🚀 创建项目。
我们将为该项目命名:(zustand-tutorial
可选,您可以随意命名)。
npm init vite@latest
我们使用 Vite JS 创建项目,并选择 React with TypeScript。
然后运行以下命令导航到刚刚创建的目录。
cd zustand-tutorial
然后我们安装依赖项。
npm install
然后我们在代码编辑器中打开项目(在我的情况下是 VS 代码)。
code .
🚀 创建商店。
首先我们必须安装 Zustand:
npm install zustand
安装库后,我们需要创建一个文件夹src/store
,并在文件夹内添加一个名为的新文件bookStore.ts
,然后在此文件内创建我们的商店。
首先我们导入 zustand 包并命名它bookStore.ts
。创建
import create from 'zustand';
然后我们创建一个名为useBookStore 的常量(这是因为 zustand 在下面使用了钩子,并且在其文档中以这种方式命名商店)。
为了定义商店,我们使用创建函数。
import create from 'zustand';
export const useBookStore = create();
创建函数以回调函数作为参数,返回一个对象来创建存储。
import create from 'zustand';
export const useBookStore = create( () => ({
}));
为了更好地自动完成,我们将使用接口来定义我们商店的属性以及功能。
然后我们设置属性的初始值,在本例中,amount属性初始为40。
import create from 'zustand';
interface IBook {
amount: number
}
export const useBookStore = create<IBook>( () => ({
amount: 40
}));
🚀 访问商店。
要访问我们的商店,我们需要导入我们的商店。
在我们的src/App.tsx
文件中,我们导入了我们的商店。
无需像在 Redux 中那样使用提供程序,我们几乎可以在任何地方使用我们的商店(“几乎”是因为它遵循钩子的规则,因为商店基本上是下面的钩子)。
基本上,我们像调用其他钩子一样调用我们的钩子,只是通过参数,我们必须通过回调来指示我们想要获取商店的属性,并且感谢自动完成功能对我们有很大帮助。
import { useBookStore } from './store/bookStore';
const App = () => {
const amount = useBookStore(state => state.amount)
return (
<div>
<h1>Books: {amount} </h1>
</div>
)
}
export default App
⭕ 访问多个状态。
假设您的商店中有多个州,例如,让我们添加标题:
import create from 'zustand';
interface IBook {
amount: number
author: string
}
export const useBookStore = create<IBook>( () => ({
amount: 40,
title: "Alice's Adventures in Wonderland"
}));
要访问更多状态,我们可以执行以下操作:
情况 1 - 一种方法是单独访问状态,创建新的常量。
import { useBookStore } from './store/bookStore';
const App = () => {
const amount = useBookStore(state => state.amount)
const title = useBookStore(state => state.title)
return (
<div>
<h1>Books: {amount} </h1>
</div>
)
}
export default App
情况 2 - 但如果您愿意,也可以创建一个具有多个状态或属性的对象。为了使 Zusand 对象进行浅层扩散,我们必须传递shallow函数。
import shallow from 'zustand/shallow'
import { useBookStore } from './store/bookStore';
const App = () => {
const { amount, title } = useBookStore(
(state) => ({ amount: state.amount, title: state.title }),
shallow
)
return (
<div>
<h1>Books: {amount} </h1>
<h4>Title: {title} </h4>
</div>
)
}
export default App
尽管如果商店的属性增长过多,最好将其放置在单独的挂钩中。
在情况 1 和情况 2 中,当标题和金额发生变化时,组件都会被渲染。
🔴 为什么要使用 shallow 函数?
在我们访问存储的几个状态的上述情况下,我们使用了浅层函数,为什么?
默认情况下,如果我们不使用浅层,Zusand 会使用严格相等(old === new)检测变化,这对于原子状态来说是有效的。
const amount = useBookStore(state => state.amount)
但在情况 2 中,我们获得的不是原子状态,而是对象(如果我们使用数组,也会发生同样的情况)。
const { amount, title } = useBookStore(
(state) => ({ amount: state.amount, title: state.title }),
shallow
)
因此,在这种情况下,默认的严格相等性对于评估对象是没有用的,即使对象没有改变,也总是触发重新渲染。
因此,Shallow将上传对象/数组并比较其键,如果有任何不同,它将再次重新创建并触发新的渲染。
🚀 更新状态。
要更新商店中的状态,我们必须通过创建新属性来src/store/bookStore.ts
添加函数来更新修改商店。
在接收创建函数的回调中,该函数接收几个参数,第一个是设置函数,它将允许我们更新商店。
export const useBookStore = create<IBook>(( set ) => ({
amount: 40
}));
⭕ 创建一个动作。
首先,我们创建一个新属性来更新金额,它被称为updateAmount,它接收一个数字作为参数。
import create from 'zustand'
interface IBook {
amount: number
updateAmount: (newAmount: number) => void
}
export const useBookStore = create<IBook>((set) => ({
amount: 40,
updateAmount: (newAmount: number ) => {}
}));
在updateAmount函数的主体中,我们通过发送一个对象来执行设置函数,引用要更新的属性。
import create from 'zustand'
interface IBook {
amount: number
updateAmount: (newAmount: number) => void
}
export const useBookStore = create<IBook>( (set) => ({
amount: 40,
updateAmount: (newAmount: number ) => set({ amount: newAmount }),
}));
set函数还可以接收一个函数作为参数,这对于获取之前的状态很有用。
或者,我分散整个状态(假设我有更多的属性)并且只更新我需要的状态,在本例中是数量。
注意:当您的状态是不断变化的对象或数组时,还应该考虑扩展属性。
updateAmount: (newAmount: number ) => set( state => ({ ...state, amount: state.amount + newAmount }))
您还可以按如下方式执行异步操作,就是这样!
updateAmount: async(newAmount: number ) => {
// to do fetching data
set({ amount: newAmount })
}
💡 注意:set函数接受第二个布尔参数,默认值为 false。它不会合并状态模型,而是会替换状态模型。请务必小心,不要删除 store 中的重要部分,例如操作。
updateAmount: () => set({}, true), // clears the entire store, actions included,
⭕ 访问商店中存储的状态。
为了定义状态,我们使用设置函数,但如果我们想获取状态的值怎么办?
好吧,我们在set旁边有第二个参数,即get(),它使我们能够访问状态。
import create from 'zustand'
interface IBook {
amount: number
updateAmount: (newAmount: number) => void
}
export const useBookStore = create<IBook>( (set, get) => ({
amount: 40,
updateAmount: (newAmount: number ) => {
const amountState = get().amount
set({ amount: newAmount + amountState })
//is the same as:
// set(state => ({ amount: newAmount + state.amount }))
},
}));
⭕ 执行操作。
要执行该操作,只需像之前一样访问属性即可。然后我们执行它,并发送必要的参数(在本例中只是一个数字)。
import { useBookStore } from './store/bookStore';
const App = () => {
const amount = useBookStore(state => state.amount)
const updateAmount = useBookStore(state => state.updateAmount)
return (
<div>
<h1> Books: {amount} </h1>
<button
onClick={ () => updateAmount(10) }
> Update Amount </button>
</div>
)
}
export default App
🚀 结论。
Zusand 提供轻松访问和更新状态,这使其成为其他状态管理器的友好替代品。
就我个人而言,Zusand 的上述功能让我非常满意,它是我最喜欢的状态管理库之一,以及 Redux Toolkit。你绝对应该在项目中尝试一下 😉。
我希望我已经帮助你更好地理解了这个库是如何工作的以及如何使用它,非常感谢你读到这里!🤗
如果您知道 Zustand 的任何其他重要功能或代码的最佳实践,欢迎您发表评论。🙌
鏂囩珷鏉ユ簮锛�https://dev.to/franklin030601/using-zustand-with-react-js-9di