美文网首页
react_15Hooks_二(初步了解redux,手动实现过程

react_15Hooks_二(初步了解redux,手动实现过程

作者: 小话001 | 来源:发表于2022-10-26 10:21 被阅读0次

    上:

    JavaScript纯函数:
    • 确定的输入,一定会产生确定的输出;
    • 函数在执行过程中,不能产生副作用;
      React中要求我们无论是函数还是class声明一个组件,这个组件必须是像纯函数一样,保护props不被修改,redux中,reducer要求是一个纯函数
      (一):Redux定义:是JavaScript状态容器,提供了可预测的状态管理
    核心理念——store

    管理数据

    const initialState = {
      counter: 0
    }
    
    核心理念——action

    所有数据的变化,必须通过派发(dispatch) action来更新;
    它是一个普通的js对象,用来描述这次更新的type和content;

    // actions
    const action1 = { type: "INCREMENT" };
    const action2 = { type: "DECREMENT" };
    
    const action3 = { type: "ADD_NUMBER", num: 5 };
    const action4 = { type: "SUB_NUMBER", num: 12 };
    
    核心理念——reducer

    它是一个纯函数;负责将传入的state和action结合起来生成一个新的state;

    // reducer
    function reducer(state = initialState, action) {
      switch (action.type) {
        case "INCREMENT":
          return { ...state, counter: state.counter + 1 }
        case "DECREMENT":
          return { ...state, counter: state.counter - 1 }
        case "ADD_NUMBER":
          return { ...state, counter: state.counter + action.num }
        case "SUB_NUMBER":
          return { ...state, counter: state.counter - action.num }
        default:
          return state;
      }
    }
    

    结合使用:

    // store(创建的时候需要传入一个reducer)
    const store = redux.createStore(reducer)
    // 订阅store的修改
    store.subscribe(() => {
      console.log("counter:", store.getState().counter);
    })
    
    // 派发action
    store.dispatch(action1);
    store.dispatch(action2);
    store.dispatch(action2);
    store.dispatch(action3);
    store.dispatch(action4);
    
    完整测试案例:
    1. yarn init
    2. yarn add redux
    3. 创建src目录,创建index.js
    4. 修改package.json执行index.js
    “scripts”:{
      "start": "node src/index.js"
    }
    

    注意: 从node v13.2.0开始,node才对ES6模块化提供了支持。
    node v13.2.0之前,需要进行如下操作:
    在package.json中添加属性: "type": "module";
    在执行命令中添加如下选项:node --experimental-modules src/index.js;
    node v13.2.0之后,只需要进行如下操作:
    在package.json中添加属性: "type": "module"

    目录结构:
    store/index.js

    import redux from 'redux';
    
    import reducer from './reducer.js';
    
    const store = redux.createStore(reducer);
    
    export default store;
    

    store/reducer.js

    import {
      ADD_NUMBER,
      SUB_NUMBER,
      INCREMENT,
      DECREMENT
    } from './constants.js';
    
    const defaultState = {
      counter: 0
    }
    
    function reducer(state = defaultState, action) {
      switch (action.type) {
        case ADD_NUMBER:
          return { ...state, counter: state.counter + action.num };
        case SUB_NUMBER:
          return { ...state, counter: state.counter - action.num };
        case INCREMENT:
          return { ...state, counter: state.counter + 1 };
        case DECREMENT:
          return { ...state, counter: state.counter - 1 };
        default:
          return state;
      }
    }
    export default reducer;
    

    store/actionCreators.js

    import {
      ADD_NUMBER,
      SUB_NUMBER,
      INCREMENT,
      DECREMENT
    } from './constants.js';
    
    // 写法一:
    // export function addAction(num) {
    //   return {
    //     type: "ADD_NUMBER",
    //     num
    //   }
    // }
    
    // 写法二:
    // export const addAction = (num) => {
    //   return {
    //     type: "ADD_NUMBER",
    //     num
    //   }
    // }
    
    // 写法三:
    export const addAction = num => ({
      type: ADD_NUMBER,
      num
    });
    
    export const subAction = num => ({
      type: SUB_NUMBER,
      num
    });
    
    export const incAction = () => ({
      type: INCREMENT
    });
    
    export const decAction = () => ({
      type: DECREMENT
    });
    

    store/constants.js

    export const ADD_NUMBER = "ADD_NUMBER";
    export const SUB_NUMBER = "SUB_NUMBER";
    export const INCREMENT = "INCREMENT";
    export const DECREMENT = "DECREMENT";
    
    完整react+redux案例:
    目录结构.jpg

    src/index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    
    ReactDOM.render(
        <App />
      document.getElementById('root')
    );
    

    src/App.js

    import React, { PureComponent } from 'react';
    
    import Home from './pages/home';
    import About from './pages/about';
    
    export default class App extends PureComponent {
      render() {
        return (
          <div>
            <Home/>
            <About/>
          </div>
        )
      }
    }
    

    src/store/index.js

    import { createStore } from 'redux';
    iimport reducer from './reducer.js';
    const store = createStore(reducer);
    
    export default store; 
    

    其它三个文件store/actionCreators.js、store/reducer.js、store/constants.js不变;
    src/store/index.js



    pages/about.js
    核心:

    componentDidMount 中定义数据的变化,当数据发生变化时重新设置 counter;
    在发生点击事件时,调用store的dispatch来派发对应的action

    import React, { PureComponent } from 'react';
    
    import store from '../store';
    import {  subAction } from "../store/actionCreators";
    
    export default class About extends PureComponent {
      constructor(props) {
        super(props);
    
        this.state = {
          counter: store.getState().counter
        }
      }
    
      componentDidMount() {
        this.unsubscribue = store.subscribe(() => {
          this.setState({
            counter: store.getState().counter
          })
        })
      }
    
      componentWillUnmount() {
        this.unsubscribue();
      }
    
      render() {
        return (
          <div>
            <hr/>
            <h1>About</h1>
            <h2>当前计数: {this.state.counter}</h2>
            <button onClick={e => this.decrement()}>-1</button>
            <button onClick={e => this.subNumber(5)}>-5</button>
          </div>
        )
      }
    
      decrement() {
        store.dispatch(subAction(1));
      }
    
      subNumber(num) {
        store.dispatch(subAction(num));
      }
    }
    

    pages/home.js

    import React, { PureComponent } from "react";
    
    import store from "../store";
    
    import { addAction } from "../store/actionCreators";
    
    export default class Home extends PureComponent {
      constructor(props) {
        super(props);
    
        this.state = {
          counter: store.getState().counter,
        };
      }
    
      componentDidMount() {
        this.unsubscribue = store.subscribe(() => {
          this.setState({
            counter: store.getState().counter,
          });
        });
      }
    
      componentWillUnmount() {
        this.unsubscribue();
      }
    
      render() {
        return (
          <div>
            <h1>Home</h1>
            <h2>当前计数: {this.state.counter}</h2>
            <button onClick={(e) => this.increment()}>+1</button>
            <button onClick={(e) => this.addNumber(5)}>+5</button>
          </div>
        );
      }
    
      increment() {
        store.dispatch(addAction(1));
      }
    
      addNumber(num) {
        store.dispatch(addAction(num));
      }
    }
    

    代码在下部分优化

    相关文章

      网友评论

          本文标题:react_15Hooks_二(初步了解redux,手动实现过程

          本文链接:https://www.haomeiwen.com/subject/penazrtx.html