【分享】使用 Reducer 和 Context 拓展你的应用

前言

本篇文章旨在探讨Reducer与Context在扩展应用程序中的应用技巧及其实战思路。如果你发现其中的任何错误或有更加高效的解决方案,恳请在评论区不吝赐教,共同交流进步。

1.搭建react项目

可以浏览从零搭建react项目(简易版)搭建项目。

2.结合使用 reducer 和 context

  1. 创建 context。
  2. 将 state 和 dispatch 放入 context。
  3. 在组件树的任何地方 使用 context。
2.1创建 context
  1. 在src目录下创建redux文件夹并创建index.js文件
    index.js内容如下:
import { createContext } from "react";
export const TasksContext = createContext(null);
export const TasksDispatchContext = createContext(null);

export const initialTasks = {
  count: 0,
};

export const tasksReducer = (state, action) => {
  switch (action.type) {
    case "add":
      return {
        ...state,
        count: ++state.count,
      };
    case "reduce":
      return {
        ...state,
        count: --state.count,
      };
    default:
      break;
  }
};
2.2将 state 和 dispatch 放入 context
  1. 在src目录下创建components文件夹
  2. 在components文件夹创建Provider文件夹并创建index.jsx文件
    index.js内容如下:
import React, { useReducer } from "react";
import {
  TasksContext,
  TasksDispatchContext,
  tasksReducer,
  initialTasks,
} from "../../redux/index.js";

export const Provider = ({ children }) => {
  const [state, dispatch] = useReducer(tasksReducer, initialTasks);
  return (
    <TasksContext.Provider value={state}>
      <TasksDispatchContext.Provider value={dispatch}>
        {children}
      </TasksDispatchContext.Provider>
    </TasksContext.Provider>
  );
};
2.3在组件树的任何地方 使用 context。
  1. 在src文件夹下创建hooks文件夹并在hooks文件夹下创建useRedux.js文件
    useRedux.js内容如下:
import { useContext } from "react";
import { TasksContext, TasksDispatchContext } from "../redux";
export const useRedux = () => {
  const state = useContext(TasksContext);
  const dispatch = useContext(TasksDispatchContext);
  return {
    state,
    dispatch,
  };
};
  1. 在src文件夹下创建pages文件夹并在pages文件夹下创建Home文件夹并在Home文件夹下创建index.jsx文件
    index.jsx内容如下:
import React from "react";
import { useRedux } from "../../hooks/useRedux";
export const Home = () => {
  const { state, dispatch } = useRedux();

  return (
    <div>
      <button
        onClick={() => {
          dispatch &&
            dispatch({
              type: "reduce",
            });
        }}
      >
        减少
      </button>
      {state?.count}
      <button
        onClick={() => {
          dispatch &&
            dispatch({
              type: "add",
            });
        }}
      >
        增加
      </button>
    </div>
  );
};
  1. 修改app.js文件内容如下:
import React from "react";
import icon from "./icon.png";
import { Provider } from "./components/Provider/index.jsx";
import { Home } from "./pages/Home";
import "./app.css";
import "./app.less";

export const App = () => {
  return (
    <Provider>
      <div className="hello fs60">
        app
        <img src={icon} />
        <Home />
      </div>
    </Provider>
  );
};

3.小结

至此,我们已按照官方文档完成了基本的实施步骤。接下来,我将分享自己在实际操作中积累的一些心得体验。诚挚邀请各位指出可能存在的疏漏与错误,并欢迎提供更加优秀的策略与建议,让我们在相互学习中共同成长。

4.更新如下

"低耦合"的核心理念在于,作为软件开发的关键设计原则,它极力促进系统组件间的独立性,力求将相互依赖降至最低。这要求每一模块、类或服务专精于其独特的功能领域,能够脱离系统其他部分而单独进行开发、测试及部署流程。这一原则显著增强了软件的可重用性、维护便利度及灵活性,确保对任一模块的调整或替换不会波及系统全局,引发连带效应。要实现这一目标,常见的实践包括采用接口编程、依赖注入机制、推行模块化架构设计,以及坚守单一职责原则,以此策略织就软件的韧性与可扩展性。

  1. 在src目录下redux文件夹下创建actions文件夹并在该文件夹下创建global.js和index.js文件
    global.js内容如下:
export const actions = {
  addCount() {
    return {
      type: "global.addCount",
    };
  },
  reduceCount() {
    return {
      type: "global.reduceCount",
    };
  },
  changeLoading(status) {
    return {
      type: "global.changeLoading",
      preload: status,
    };
  },
};

export const reducer = {
  addCount(state, action) {
    return {
      ...state,
      count: ++state.count,
    };
  },
  reduceCount(state, action) {
    return {
      ...state,
      count: --state.count,
    };
  },
  changeLoading(state, action) {
    return {
      ...state,
      loading: action.preload,
    };
  },
};

index.js文件如下:

import * as global from "./global";

export default {
  global,
};

  1. 修改redux文件下index.js内容如下:
import { createContext } from "react";
import actions from "./actions";
export const initialTasks = {
  count: 0,
  loading: false,
};
export const TasksContext = createContext(initialTasks);

const deconstructionActionType = (type) => {
  if (!type) {
    return null;
  }
  if (typeof type !== "string") {
    return null;
  }
  if (!type.includes(".")) {
    return null;
  }
  const [parentKey, reducerKey] = type.split(".");
  return {
    parentKey,
    reducerKey,
  };
};

export const tasksReducer = (state, action) => {
  const keys = deconstructionActionType(action.type);
  if (keys !== null) {
    const { parentKey, reducerKey } = keys;
    if (
      typeof actions[parentKey] === "object" &&
      typeof actions[parentKey].reducer === "object" &&
      typeof actions[parentKey].reducer[reducerKey] === "function"
    ) {
      return actions[parentKey].reducer[reducerKey](state, action);
    }
  }
};

export const buildDispatch = (dispatch) => {
  const buildActions = {};
  const parentKeys = Object.keys(actions);

  const dealWithItemActions = (parentKey) => {
    const item = actions[parentKey];
    const itemActionKeys = Object.keys(item.actions);
    for (let index = 0; index < itemActionKeys.length; index++) {
      const actionKey = itemActionKeys[index];
      if (typeof item.actions[actionKey] === "function") {
        buildActions[parentKey][actionKey] = (...args) => {
          dispatch(item.actions[actionKey](...args));
        };
      }
    }
  };

  for (let index = 0; index < parentKeys.length; index++) {
    const parentKey = parentKeys[index];
    if (typeof actions[parentKey].actions === "object") {
      !buildActions[parentKey] && (buildActions[parentKey] = {});
      dealWithItemActions(parentKey);
    }
  }
  return buildActions;
};

  1. 修改components文件夹下Provider文件夹下index.jsx内容如下:
import React, { useReducer, useRef } from "react";
import {
  TasksContext,
  tasksReducer,
  initialTasks,
  buildDispatch,
} from "../../redux/index.js";

export const Provider = ({ children }) => {
  const [state, dispatch] = useReducer(tasksReducer, initialTasks);
  const actions = useRef(buildDispatch(dispatch));
  return (
    <TasksContext.Provider
      value={{ state, dispatch, actions: actions.current }}
    >
      {children}
    </TasksContext.Provider>
  );
};

  1. 修改hooks文件夹下useRedux.js文件内容如下:
import { useContext } from "react";
import { TasksContext } from "../redux";
export const useRedux = () => {
  const { state, dispatch, actions } = useContext(TasksContext);
  return {
    state,
    dispatch,
    actions,
  };
};

  1. 修改pages文件夹下Home文件夹下index.jsx内容如下:
import React from "react";
import { useRedux } from "../../hooks/useRedux";
export const Home = () => {
  const { state, actions } = useRedux();
  return (
    <div>
      <button
        onClick={() => {
          actions.global.reduceCount();
        }}
      >
        减少
      </button>
      {state.count}
      <button
        onClick={() => {
          actions.global.addCount();
        }}
      >
        增加
      </button>
      <button
        onClick={() => {
          actions.global.changeLoading(!state.loading);
        }}
      >
        {state.loading ? "停止" : "开始"}
      </button>
    </div>
  );
};

5.总结

以上均为本人在实践探索中积累的经验总结,难免存在疏漏与不足之处。若您发现任何错误或拥有更佳的方法与见解,敬请在评论区慷慨分享,让我们在相互交流中共同进步,提升技能。

6.主要文献

使用 Reducer 和 Context 拓展你的应用

相关推荐

  1. 分享使用 Reducer Context 拓展应用

    2024-06-09 14:18:02       13 阅读
  2. Reducer Context实现简单Redux

    2024-06-09 14:18:02       35 阅读
  3. react之ReducerContext联合使用

    2024-06-09 14:18:02       13 阅读
  4. 数组reduce 使用扁平化处理

    2024-06-09 14:18:02       15 阅读
  5. WebFlux中使用WebSocket拓展功能分析

    2024-06-09 14:18:02       36 阅读
  6. React Context 使用详解

    2024-06-09 14:18:02       17 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-09 14:18:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-09 14:18:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-09 14:18:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-09 14:18:02       18 阅读

热门阅读

  1. 力扣2799.统计完全子数组的数目

    2024-06-09 14:18:02       11 阅读
  2. lua中大数相乘的问题

    2024-06-09 14:18:02       10 阅读
  3. LeetCode 第401场周赛个人题解

    2024-06-09 14:18:02       12 阅读
  4. 二叉树的统一迭代法-前序中序后序-力扣

    2024-06-09 14:18:02       12 阅读