本章节会完成一个简易的redux实现
目录 实现reducer、dispatch实现connect实现connect参数一selectorconnect参数-mapDispatchToProps 实现reducer该系列内容会逐步实现简易的redux
使用技术栈:vite+react
该系列感谢@方应杭 的react教学视频
在实现reducer之前,我们先简单使用基本的state *** 作来实现一个组件之间通信
import React, { useState, useContext } from "react";
import "./App.css";
// 1、创建上下文
const appContext = React.createContext(null);
const 张三 = () => {
// 获取上下文中的value和setValue方法。
const {appState,setValue} = useContext(appContext);
// 修改年龄值
function changeAge(e) {
const val = e.target.value;
setValue({ ...appState, age: val });
}
return (
<div>
<p>张三</p>
<div>
<input value={appState.user.age} onChange={changeAge} />
</div>
</div>
);
};
const 李四 = () => <div><p>李四</p>名字:{useContext(appContext).appState.user.name},年龄:{useContext(appContext).appState.user.age}</div>;
const 王五 = () => <div>王五</div>;
const App = () => {
// 定义本次演示的数据state
const [appState, setValue] = useState({
user:{
name: "张三",
age: 18,
}
});
const contextValue = { appState, setValue };
return (
<appContext.Provider value={contextValue}>
<div className="container">
<div className="box">
<张三 />
</div>
<div className="box">
<李四 />
</div>
<div className="box">
<王五 />
</div>
</div>
</appContext.Provider>
);
};
export default App;
以上代码的效果是这样:
上面的代码分别创建了:
App根组件三个子组件:张三、李四、王五以及一个上下文appContext
在App中定义了一个state:appState
我们在<张三>组件中放入一个input组件来修改value值,在李四组件中展示对应的内容。
通过useConnext
建立于数据源联系。以上代码是没问题的,每次setValue时都是一个新对象,视图会对应更新。
但是在实际业务中,会存在大量的state存储,我们要跨组件处理数据的同时,也要指定对应的规范。
接下来,我们尝试将创建新对象这个行为单独出来写一个函数,用函数来代替我们生成新state对象
// reducer
const reducer = (state,action)=>{
const { type, payload} = action;
switch(type){
case 'changeUser':
return {
...state,
user:{
...state.user,
...payload
},
};
default:
return state
}
}
// 修改年龄值
// function changeAge(e) {
// const val = e.target.value;
// const newState = reducer(appState,{type:'changeUser',payload:{age:val}});
// setValue(newState);
// }
// 优化后
function changeAge(e) {
const val = e.target.value;
setValue(reducer(appState,{type:'changeAge',payload:{age:val}}));
}
以上内容已经初步有点reducer的样子。上面的代码表示,通过reducer函数,我们传入对应的type就可以更新对应的state内容。
dispatch上一步代码中,每次修改state时,都需要写setValue(reducer(appState,xxx));
这一段,那么可以将这段代码封装成名为dispatch的函数
const dispatch = (action)=>{
setValue(reducer(appState,action))
}
// 修改年龄值
function changeAge(e) {
const val = e.target.value;
dispatch({type:'changeAge',payload:{age:val}})
}
由于dispatch需要使用serValue
,而react规定setState
函数必须要在函数组件中定义,但是又不能每个组件都定义一个这样的方法。
可以利用高阶组件包装一下
// 创建一个createWrapper函数,用于包装组件
//const createWrapper = (Component) => {
// const Wrapper = (props) => { // 组件也会有自己的props,要传递给他
// const { appState, setValue } = useContext(appContext);
// const dispatch = (action) => {
// setValue(reducer(appState, action));
// };
// return ;
// };
// return Wrapper
//};
// 优化一下上面代码
const createWrapper = (Component) => {
return (props) => {
const { appState, setValue } = useContext(appContext);
const dispatch = (action) => {
setValue(reducer(appState, action));
};
return <Component dispatch={dispatch} state={appState} {...props}/>;
};
};
const 张三Wrapper = createWrapper(张三);
const App = () => {
// 定义本次演示的数据state
const [appState, setValue] = useState({
name: "张三",
age: 18,
});
const contextValue = { appState, setValue };
return (
<appContext.Provider value={contextValue}>
<div className="container">
<div className="box">
<张三Wrapper />
</div>
<div className="box">
<李四 />
</div>
<div className="box">
<王五 />
</div>
</div>
</appContext.Provider>
);
};
export default App;
效果
至此,一个简单的reducer和dispatch就完成。
总结我们通过useConnext建立的上下文联系,在上文中定义了全局state,之后下传至每一个组件,通过reducer规范了构建全局新state的过程,又通过dispatch简化了修改state值的行为。而reducer和dispatch的作用也恰是如此,只不过我们的比较简易实现。
但是! 以上代码还是存在问题的,后续会提出。 错误的地方欢迎指正
未完待续欢迎分享,转载请注明来源:内存溢出
评论列表(0条)