zustand 状态管理库的使用 结合TS

zustand 是一个用于React应用的简单、快速且零依赖的状态管理库。它使用简单的钩子(hooks)API来创建全局状态,使得在组件之间共享状态变得容易。
React学习Day10

基本用法

  1. 安装:首先,你需要安装zustand库。

    npm install zustand
    
  2. 创建一个状态存储:使用createStore函数来创建一个新的状态存储。

  3. 设置初始状态:你可以提供一个对象作为初始状态,对象的每个属性都将成为状态的一部分。

  4. 定义状态更新函数:这些函数可以修改状态存储中的状态。

  5. 使用状态:在组件中使用useStore钩子来访问和更新状态。

代码示例

以下是一个使用zustand的基本示例:

store / user.tsx 中创建一个状态

import { create } from "zustand";

interface Store {
  count: number;
  inc: (num: number) => void;
}
// 这里的  表示 create 函数接受一个泛型参数,这个参数是 Store 接口的类型。
// 相当于在调用函数的时候指定type参数,类似 fun1(1);
const createUserStore = create<Store>((set) => {
  return {
    count: 0,
    inc: (num: number) => {
      set((state) => ({ count: state.count + num }));
    },
  };
});



export default createUserStore;

在组件中使用这个状态
component / Son.tsx

import React from "react";
import createUserStore from "../store/user";  // 引入

interface SonProps {
  data: number; 
  changeFatherMoney: (data: number) => void; 
}

const Son: React.FC<SonProps> = ({ data, changeFatherMoney }) => {
  const { count, inc } = createUserStore();  // 导出
  return (
    <div style={{ border: "1px red solid" }}>
      <div>用户信息counter:{count}</div>
      <button
        onClick={() => {
          inc(10);
        }}
      >
        +10
      </button>
      <p>这里是子组件</p>
      父亲的数据是:{data}
      <button onClick={() => changeFatherMoney(data - 1)}>用父亲一块钱</button>
    </div>
  );
};

export default Son

泛型介绍

在TypeScript中, 是一个泛型参数的表示方式。这里的 表示 create 函数接受一个泛型参数,这个参数是 Store 接口的类型。

泛型在TypeScript中是一种强大的方式,允许你为函数、接口或类定义类型参数,这些参数在定义时不必指定具体的类型,而是在使用时指定。这样做可以提高代码的复用性和灵活性。

在你给出的示例中:

interface Store {
  count: number;
  inc: (num: number) => void;
}

const createUserStore = create<Store>((set) => {
  return {
    count: 0,
    inc: (num: number) => {
      set((state) => ({ count: state.count + num }));
    },
  };
});

这里的泛型,规定了create的返回值类型,返回的状态存储对象的类型,而不是用来规定参数类型。

create 表示 create 函数接受一个泛型参数 Store。这个泛型参数是类型接口 Store,它定义了 store 的形状,即包含 count 和 inc 属性。
在这里不是对泛型参数进行约束,而是直接指定了 create 函数所使用的泛型类型,规定了返回的对象必须是否符合 Store 接口的定义

  • interface Store 定义了一个接口,其中包含一个 count 属性和一个 inc 方法。
  • createzustandcreate 函数,它被调用时使用了泛型参数 。这意味着 create 函数将创建一个状态存储,其形状(state shape)将由 Store 接口定义。
  • createUserStore 是一个函数,当调用时会返回一个符合 Store 接口的状态存储实例。

为什么在 Zustand 中使用泛型而不是接口

在 Zustand 的 create 函数中,泛型不仅用于指定返回值的类型,还用于定义函数内部 set 方法的参数类型等,这比单独使用接口来定义返回值类型更具优势。

示例代码
import { create } from "zustand";

interface Store {
  count: number;
  inc: (num: number) => void;
}

const createUserStore = create<Store>((set) => {
  return {
    count: 0,
    inc: (num: number) => {
      set((state) => ({ count: state.count + num }));
    },
  };
});
解释
  1. 泛型的作用

    • create 中的 泛型不仅指定了 createUserStore 的返回值类型,也规定了回调函数参数 set 的类型。
    • set 函数的类型定义需要知道 Store 的结构,以便 TypeScript 可以正确推断 setstate 的类型。
  2. 接口的局限性

    • 如果只使用接口来定义返回值类型,会失去对 set 函数类型的类型推断和约束。
    • 接口无法单独定义 create 函数返回的回调函数 set 的参数类型。
示例:如果只用接口定义返回值类型

如果只用接口定义返回值类型,无法涵盖 set 函数类型的约束:

const createUserStore = create((set: (fn: (state: Store) => Store) => void) => {
  return {
    count: 0,
    inc: (num: number) => {
      set((state) => ({ count: state.count + num }));
    },
  };
} as Store);

这种方式缺乏泛型提供的灵活性和类型推断能力,代码变得不那么优雅,类型定义也不那么清晰。

总结

  1. 泛型用途广泛:泛型不仅可以规定返回值类型,还可以用于函数参数、类属性和方法、接口属性和方法、类型别名等。
  2. Zustand 中使用泛型的优势:在 Zustand 的 create 函数中使用泛型,不仅规定了返回值类型,还涵盖了内部回调函数 set 的参数类型约束,使代码更加类型安全和简洁。
  3. 接口的局限性:仅使用接口来定义返回值类型,无法对函数参数类型进行全面约束,失去了泛型提供的类型推断能力。

通过使用泛型,你可以使代码更具通用性、灵活性和类型安全性,特别是在处理复杂的类型结构时。

调试工具

npm i simple-zustand-devtools -D

import create from 'zustand'

// 导入核心方法
import { mountStoreDevtool } from 'simple-zustand-devtools'

// 省略部分代码...


// 开发环境开启调试
if (process.env.NODE_ENV === 'development') {
  mountStoreDevtool('channelStore', useChannelStore)
}


export default useChannelStore

zustand 状态管理库的使用 结合TS_第1张图片

注意事项

  • zustand的状态存储是单一的,意味着所有组件共享相同的状态副本。
  • 状态更新是响应式的,组件会在状态变化时重新渲染。
  • 状态存储的创建应该是一次性的,通常在单独的文件中进行,然后被多个组件导入和使用。

zustand是一个轻量级的状态管理解决方案,特别适合中小型项目或者需要快速设置全局状态的场景。

你可能感兴趣的:(ts开发知识,react)