使用useContext封装一个小型全局数据存储共享工具hook

如何在React中使用自定义Hook管理全局状态

在构建React应用时,我们经常需要跨多个组件共享状态。虽然Redux等状态管理库在大型应用中表现出色,但对于小到中等规模的项目来说,它们可能显得过于复杂。在这篇文章中,我将向你展示如何使用React的useState和useContext钩子创建自定义Hook来管理全局状态,同时演示如何有效地执行批量状态更新以防止状态覆盖

创建Context和Provider

首先,我们需要创建一个上下文和一个对应的提供者(Provider)来传递状态。

store 文件夹中定义index.tsx文件

import { createContext, ReactNode, useContext, useState } from "react";
import { DefinedState, initState } from "./defined.ts";

/* 定义 SetStateAction   */
type SetStateAction = {
  [P in keyof DefinedState]?: DefinedState[P];
};

// 定义 context 的类型
interface ContextType {
  state: DefinedState;
  setState: (action: SetStateAction) => void;
}

// 使用断言定义一个“空”的 context,并赋予后面会使用的类型
const ContextBody = createContext<ContextType>({} as ContextType);

export function ContentProvider({ children }: { children: ReactNode }) {
  const [state, changeState] = useState<any>(initState);

  const setState = (
    action: SetStateAction | ((prevState: DefinedState) => SetStateAction)
  ) => {
    changeState((prevState: DefinedState) => {
      // 如果action是一个函数,传递prevState给这个函数来获取新状态
      const newState =
        typeof action === "function" ? action(prevState) : action;
      // 合并旧状态与新状态
      return { ...prevState, ...newState };
    });
  };
  return (
    <ContextBody.Provider value={{ state, setState }}>
      {children}
    </ContextBody.Provider>
  );
}

export function useStateHook() {
  return useContext(ContextBody);
}

store文件下创建defined.ts文件

/* 定义state数据类型和默认值 */

/** state数据集合 */
export interface DefinedState {
    /*  测试数据  */
    test1: string;
    /* 测试数据2  */
    test2: string;
}

/* 将所有类型变成可选 */
type OptionalDefinedState = Partial<DefinedState>;

export const initState: OptionalDefinedState = {
    test1: '我是测试数据',
    test2: '我是测试数据2',
};

在组件中使用自定义Hook

在我们的APP.tsx中,将我们的hook包裹这个组件

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { ContentProvider } from "./store/index.tsx";

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <ContentProvider>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </ContentProvider>
);

在我们开发过程中我们只需要引用我们的仓库即可操作获取数据,使用这个自定义Hook,组件可以访问共享状态并可以更新它。

import React from "react";
import { useStateHook } from "./store/index";
import { Input } from "antd";

function App() {
  const { state, setState } = useStateHook();
  const { test1, test2 } = state;
  return (
    <>
      {test1}
      <Input
        placeholder="输入test1"
        onPressEnter={(e: any) => {
          setState({ test1: e.target.value });
          setState({ test2: e.target.value });
        }}
      />
      <br />
      {test2}
      <Input
        placeholder="请输入test2"
        onPressEnter={(e: any) => setState({ test2: e.target.value })}
      />
      <br />
    </>
  );
}

export default App;

Redux和使用useState与useContext结合的自定义Hook方法是用于在React应用中管理状态的两种不同方案。它们各有优缺点,并分别适合于不同的场景

比较

Redux

优点:
  1. 预测性强:Redux通过限制更新逻辑并通过纯函数来执行,提供了一个可以预测的状态更新方法。
  2. 中央化管理:Redux提供一个单一的状态树来管理应用的所有状态,使得状态管理更加一致和透明。
  3. 强大的中间件生态:Redux有着丰富的中间件,可以轻易地处理例如异步操作、日志记录等高级场景。
  4. 开发工具:Redux有很好的开发调试工具,例如Redux DevTools。
    社区和生态系统:Redux有一个大且成熟的社区支持,以及大量的教程、例子和最佳实践。
缺点:
  1. 引入了额外的复杂性和引导概念,有一定的学习曲线。
    对于小型或简单的应用来说,可能过于笨重。
  2. 代码样板较多,需要编写额外的action creators、reducers等。
    需要遵守特定的Redux框架代码结构,可能需要调整代码设计。
适用场景:
  1. 大型或复杂的应用,尤其是需要多个组件访问同一状态的场景。
  2. 需要强大的状态管理功能,例如异步逻辑、日志记录、持久化、服务器端渲染等。
  3. 应用中有复杂的数据处理和业务逻辑的地方。

使用useState与useContext结合的自定义Hook方法

优点:
  1. 简化状态管理:较少的样板代码,没有那么多固定的模式,更简洁的API。
  2. 更符合React的函数式编程模式:直接使用React的内置Hook,不需要引入额外的库。
  3. 灵活性高:容易修改和维护状态逻辑。
  4. 状态逻辑集中在组件中,易于理解。
缺点:
  1. 对于复杂的全局状态管理,可能导致Provider组件层级过深。
  2. 缺少中间件生态系统,不那么容易处理复杂的异步流和副作用。
  3. 状态更新逻辑可能散布于组件间,导致难以追踪和理解。
  4. 没有Redux DevTools这样强大的开发工具来进行时光机式的调试。
适用场景:
  1. 中小型的应用,或状态相对简单的应用。
  2. 当Reducer逻辑较简单,且不需要太多中间件来处理复杂业务逻辑时。
  3. 项目开始阶段或原型开发,需要快速搭建状态管理而不引入复杂性。

总的来说,Redux是一个功能强大的全局状态管理解决方案,适合那些需要可预测且复杂的状态更新逻辑的大型应用。而自定义Hook结合useState和useContext的方案是一个更轻量级、简单的状态管理方法,非常适合小到中型应用或者那些需要快速开发和原型制作的项目。选择哪个方案应基于项目的具体需求和开发团队的熟悉度。

  • 20
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光头程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值