React状态管理库—— zustand 为啥这么简单易用🚀

本文涉及的产品
简介: React状态管理库—— zustand 为啥这么简单易用🚀

GitHub地址:https://github.com/pmndrs/zustand/tree/main

🚀 简单易用的 zustand

🚀 简单的对比

说到中大型React项目状态管理库,最先想到就是Redux。而Redux是基于Flux架构模式的状态管理库。

Redux继承了Flux"单向流动"的特点,

  1. 用户与 View 进行交互,触发相应的 Actions
  2. Actions 通过 Dispatcher 进行派发。
  3. Stores 接收派发的 Actions,并根据需要更新状态。
  4. Stores 更新后触发事件,通知 Views 进行界面更新。
  5. Views 使用 Stores 中的最新状态重新渲染界面。

然而随着Hook的流行,Flux模式显得日益笨重。在很长时间里,通常会采用react自带的createContext代替Redux的需求。一个简单的例子如下。

import React, { createContext, useContext, useState } from 'react';
// 创建一个上下文对象类型
interface CountContextProps {
  count: number;
  setCount: (count: number) => void;
}
// 创建上下文
const CountContext = createContext<CountContextProps | undefined>(undefined);
// 提供器组件
const CountProvider: React.FC = ({ children }) => {
  const [count, setCount] = useState(0);
  const contextValue: CountContextProps = {
    count,
    setCount,
  };
  return (
    <CountContext.Provider value={contextValue}>
      {children}
    </CountContext.Provider>
  );
};
// 消费者组件
const Counter: React.FC = () => {
  const { count, setCount } = useContext(CountContext)!;
  const increment = () => {
    setCount(count + 1);
  };
  const decrement = () => {
    setCount(count - 1);
  };
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};
// 应用程序组件
const App: React.FC = () => {
  return (
    <CountProvider>
      <Counter />
    </CountProvider>
  );
};
export default App;

虽然是个简单的例子,但是实际开发中,步骤i依然繁琐。

那么有没有更简便的方案?答案是肯定的!

那就是 zustand 。同样功能的例子实现如下:

import create from 'zustand';
// 创建状态存储
interface CountState {
  count: number;
  increment: () => void;
  decrement: () => void;
}
const useCountStore = create<CountState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));
// 消费者组件
const Counter: React.FC = () => {
  const { count, increment, decrement } = useCountStore();
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};
// 应用程序组件
const App: React.FC = () => {
  return (
    <Counter />
  );
};
export default App;

简单的对比,就可以发现 zustand 没有特定的概念,简单易用。

🚀 监听变化

通常,当store变化时,可以使用 useEffect 监听状态变化

// 消费者组件
const Counter: React.FC = () => {
  const { count, increment, decrement } = useCountStore();
  useEffect(() => console.log(count), [count])
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};

但是如果当状态的变化不想引起组件的渲染时,可以使用如下方式:

// 消费者组件
const Counter: React.FC = () => {
  const { count, increment, decrement } = useCountStore();
  // useEffect(() => console.log(count), [count])
  // 注意,useCountStore.subscribe的返回值时取消订阅函数
  // 所以当组件卸载时,会自动取消订阅
  useEffect(() => useCountStore.subscribe(
    state => console.log(state.count)
  ), [])
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};

🚀 中间件模式

zustand 还在状态管理的功能上提供了中间件功能。例如,当对应的值发生变化时,自动更新localStroge

const log = (config) => (set, get, api) =>
  localStroge(
    (...args) => {
      // 这里args为set({ count })的参数就{ count }
      localStroge.setItem("count", args.count)
      set(...args)
    },
    get,
    api
  )
const useCountStore = create(
  localStroge((set) => ({
    count: 0,
    setCount: (count) => set({ count }),
  }))
)

当然,zustand提供了内置的一些中间件,如下:

export * from './middleware/redux.ts'
export * from './middleware/devtools.ts'
export * from './middleware/subscribeWithSelector.ts'
export * from './middleware/combine.ts'
export * from './middleware/persist.ts'

文档可以参看这里:https://github.com/pmndrs/zustand/blob/v4.4.1/docs/integrations/persisting-store-data.md

社区中间件也十分丰富: https://github.com/pmndrs/zustand/blob/v4.4.1/docs/integrations/third-party-libraries.md

🚀 总结

zustand 凭借小巧的体积(2kb)和简单易用的特性,迅速获得 GitHub 34.3k 的 star,足以说明它的好用。

好了今天的文章分享到这了,下篇文章我们从源码的角度进一步的认识 zustand

相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
4月前
|
资源调度 前端开发 JavaScript
React 的antd-mobile 组件库,嵌套路由
React 的antd-mobile 组件库,嵌套路由
42 0
|
6天前
|
前端开发 JavaScript API
React的Context API:全局状态管理的利器
【4月更文挑战第25天】React的Context API解决了深层组件间状态共享的难题,提供全局状态管理方案。通过`Provider`和`Consumer`组件,或结合`useContext` Hook,实现状态在组件树中的传递。最佳实践包括避免过度使用,分离逻辑,以及在必要时与Redux或MobX结合。Context API简化了数据传递,但需谨慎使用以保持代码清晰。
|
7天前
|
前端开发
探索React Hooks:一种全新的组件逻辑管理方式
React Hooks是React 16.8版本引入的一项新功能,它改变了我们编写React组件的方式。本文将从Hooks的起源讲起,逐步分析Hooks的优势,并通过具体示例展示Hooks在组件逻辑管理中的应用,旨在帮助读者更好地理解和运用React Hooks。
|
26天前
|
前端开发 数据处理 开发者
React的useState:开启组件状态管理的新篇章
React的useState:开启组件状态管理的新篇章
|
2月前
|
前端开发 Android开发 iOS开发
应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
【2月更文挑战第31天】应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
32 2
|
2月前
|
前端开发
利用React Hooks优化前端状态管理
本文将深入介绍如何利用React Hooks优化前端状态管理,包括Hooks的概念、使用方法以及与传统状态管理方式的对比分析,帮助前端开发人员更好地理解和应用这一现代化的状态管理方案。
|
4月前
|
存储 前端开发 测试技术
useReducer 的奇妙世界:探索 React 状态管理的新境界(下)
useReducer 的奇妙世界:探索 React 状态管理的新境界(下)
|
4月前
|
前端开发
useReducer 的奇妙世界:探索 React 状态管理的新境界(中)
useReducer 的奇妙世界:探索 React 状态管理的新境界(中)
|
4月前
|
前端开发 开发者
useReducer 的奇妙世界:探索 React 状态管理的新境界(上)
useReducer 的奇妙世界:探索 React 状态管理的新境界(上)
useReducer 的奇妙世界:探索 React 状态管理的新境界(上)
|
3月前
|
开发框架 前端开发 JavaScript
探索前端开发中的跨平台框架React Native
本文将介绍前端开发中一种备受关注的跨平台框架React Native,通过比较原生应用与React Native的优缺点,探讨其在实际项目中的应用以及未来发展趋势。