前言
本篇文章旨在探讨Reducer与Context在扩展应用程序中的应用技巧及其实战思路。如果你发现其中的任何错误或有更加高效的解决方案,恳请在评论区不吝赐教,共同交流进步。
1.搭建react项目
可以浏览从零搭建react项目(简易版)搭建项目。
2.结合使用 reducer 和 context
- 创建 context。
- 将 state 和 dispatch 放入 context。
- 在组件树的任何地方 使用 context。
2.1创建 context
- 在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
- 在src目录下创建components文件夹
- 在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。
- 在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,
};
};
- 在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>
);
};
- 修改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.更新如下
"低耦合"的核心理念在于,作为软件开发的关键设计原则,它极力促进系统组件间的独立性,力求将相互依赖降至最低。这要求每一模块、类或服务专精于其独特的功能领域,能够脱离系统其他部分而单独进行开发、测试及部署流程。这一原则显著增强了软件的可重用性、维护便利度及灵活性,确保对任一模块的调整或替换不会波及系统全局,引发连带效应。要实现这一目标,常见的实践包括采用接口编程、依赖注入机制、推行模块化架构设计,以及坚守单一职责原则,以此策略织就软件的韧性与可扩展性。
- 在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,
};
- 修改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;
};
- 修改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>
);
};
- 修改hooks文件夹下useRedux.js文件内容如下:
import { useContext } from "react";
import { TasksContext } from "../redux";
export const useRedux = () => {
const { state, dispatch, actions } = useContext(TasksContext);
return {
state,
dispatch,
actions,
};
};
- 修改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.总结
以上均为本人在实践探索中积累的经验总结,难免存在疏漏与不足之处。若您发现任何错误或拥有更佳的方法与见解,敬请在评论区慷慨分享,让我们在相互交流中共同进步,提升技能。