React,手写简易redux(一) - By Viga

React,手写简易redux(一)

本章节会完成一个简易的redux实现

该系列内容会逐步实现简易的redux
使用技术栈:vite+react
该系列感谢@方应杭 的react教学视频

目录

实现reducer

在实现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 <Component dispatch={dispatch}  state={appState} {...props}/>;
//  };
//  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的作用也恰是如此,只不过我们的比较简易实现。

但是! 以上代码还是存在问题的,后续会提出。 错误的地方欢迎指正

未完待续

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值