Component communication in React (react18) 04 - Getting started with redux

1 Introduction

1.1 Other ways of component communication in React

1.2 Introduction to redux

1.2.1 Refer to the official website

1.2.2 redux schematic diagram

  • The schematic diagram is as follows:
    Insert image description here
  • simple explanation
    • To update the data in state, you need to initiate an action. ActionJust a plain JavaScript object (notice that there's no magic here?) that describes what's going on.
    • The advantage of forcing the use of actions to describe all changes is that you can clearly know what is happening in the application. If something changes, you can know why. Actions are like indicators that describe what happened.
    • Finally, in order to connect action and state, some functions are developed, and this is it reducer. Again, there is no magic,reducer is just a function that receives state and action and returns new state, and is a pure function
    • The state of the entire application is stored in an object tree, and this object tree only exists storein one.

1.2.3 Basic introduction to redux

1.2.3.1 action
  • Action is the payload that transmits data from the application (not called view here because the data may be server response, user input or other non-view data) to the store. It is the only source of store data. Generally you will store.dispatch()pass the action to the store.
  • Actions are essentially plain JavaScript objects. We agree that a string type field must be used in the action to represent the action to be performed. In most cases, type will be defined as a string constant. When the application scale becomes larger and larger, it is recommended to use a separate module or file to store actions.
1.2.3.2 store
  • Store is the object that links them together. Store has the following responsibilities:
    • Maintain application state;
    • Provide getState()methods to obtain state;
    • Provide dispatch(action)methods to update state;
    • subscribe(listener)Register a listener via ;
    • By subscribe(listener) 返回的函数unregistering the listener.
  • Emphasis on Redux applicationsThere is only a single store. When you need to split data processing logic, you should use reducer combinations instead of creating multiple stores.
1.2.3.3 reducer
  • Reducers specify how the application state changes are responded to actions and sent to the store. Remember, actions only describe the fact that something happened, and do not describe how the application updates the state.
  • The reducer is a pure function that receives the old state and action and returns the new state.
  • The entire application has a single reducer function: this function is the first parameter passed to createStore. A single reducer ultimately needs to do the following:
    • The first time reducer is called, the value of state is undefined. The reducer needs to provide a default state before the action is passed in to handle this situation.
    • The reducer needs the previous state and dispatch action to decide what needs to be done.
    • Assuming that the data needs to be changed, new objects or arrays should be created with the updated data and returned.
    • If nothing has changed, the currently existing state itself should be returned.

1.3 Install redux

  • The command is as follows:
    npm install --save redux
    

2. Redux getting started example

  • Example copied directly from the official website, example address:
    https://www.redux.org.cn/ .
  • Examples are as follows:
    Insert image description here
    import {
          
           createStore } from 'redux';
    
    /**
     * 这是一个 reducer,形式为 (state, action) => state 的纯函数。
     * 描述了 action 如何把 state 转变成下一个 state。
     *
     * state 的形式取决于你,可以是基本类型、数组、对象、
     * 甚至是 Immutable.js 生成的数据结构。惟一的要点是
     * 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
     *
     * 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)
     * 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。
     */
    function counter(state = 0, action) {
          
          
      switch (action.type) {
          
          
      case 'INCREMENT':
        return state + 1;
      case 'DECREMENT':
        return state - 1;
      default:
        return state;
      }
    }
    
    // 创建 Redux store 来存放应用的状态。
    // API 是 { subscribe, dispatch, getState }。
    let store = createStore(counter);
    
    // 可以手动订阅更新,也可以事件绑定到视图层。
    store.subscribe(() =>
      console.log(store.getState())
    );
    
    // 改变内部 state 惟一方法是 dispatch 一个 action。
    // action 可以被序列化,用日记记录和储存下来,后期还可以以回放的方式执行
    store.dispatch({
          
           type: 'INCREMENT' });// 1
    store.dispatch({
          
           type: 'INCREMENT' });// 2
    store.dispatch({
          
           type: 'DECREMENT' });// 1
    
  • The effect is as follows:
    Insert image description here

3. Redux introductory example - optimization (reducer and store separated)

3.1 The effect you want to achieve

  • Because the state in the above simple example is not rendered on the page, we simply optimize it to implement the page rendering operation. The desired effect is as follows:
    Insert image description here

  • If written in pure react, it is very simple. The code is as follows:

    import {
          
           useState } from "react";
    
    function CountNum(){
          
          
        const [count,setCount] = useState(0);
    
        function add(){
          
          
            setCount(count => count+1);
        }
    
        function subtract(){
          
          
            setCount(count => count-1);
        }
    
        return(
            <div>
                当前数字是:{
          
          count}
                <br /><br />
    
                <button onClick={
          
          add}>点我 +1</button> <br /><br />
                <button onClick={
          
          subtract}>点我 -1</button>
            </div>
        )
    }
    export default CountNum;
    
  • But our goal is to use redux, so continue...

3.2 Code design

  • The project structure is as follows:
    Insert image description here
  • store.js and countReducer.js are as follows:
    Insert image description here
  • The CountNumRedux.jsx components are as follows:
    Insert image description here
  • Looking at the effect, there is a problem.
    Insert image description here
    How to re-render? continue……

3.3 Add re-rendering

3.4 Attached code

  • countReducer.js

    /**
     * 这是一个 reducer,形式为 (state, action) => state 的纯函数。
     * 描述了 action 如何把 state 转变成下一个 state。
     *
     * state 的形式取决于你,可以是基本类型、数组、对象、
     * 甚至是 Immutable.js 生成的数据结构。惟一的要点是
     * 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
     *
     * 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)
     * 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。
     */
    
    function countReducer(state = 0,action){
          
          
        console.log(`state:${
            
            state}---action:${
            
            action}---type:${
            
            action.type}`);
        switch (action.type){
          
          
            case 'INCREMENT':
                return state + 1;
            case 'DECREMENT':
                return state - 1;
            default:
                return state;
        }
    }
    export default countReducer;
    
  • store.js

    import {
          
           createStore } from 'redux';
    
    import countReducer from './countReducer.js'
    
    const store = createStore(countReducer);
    
    export default store;
    
  • CountNumRedux.jsx

    import {
          
           useState,useEffect } from "react";
    import store from '../redux/store'
    
    function CountNumRedux(){
          
          
    
        const [count,setCount] = useState(0);
    
        function add(){
          
          
            // setCount(count => count+1);
            //派发action 改变内部 state 惟一方法是 dispatch 一个 action。
            store.dispatch({
          
           type: 'INCREMENT' });
        }
    
        function subtract(){
          
          
            // setCount(count => count-1);
            store.dispatch({
          
           type: 'DECREMENT' });
        }
    
        // 可以手动订阅更新,也可以事件绑定到视图层。
        // store.subscribe(() =>
        //     console.log('订阅更新,打印1-----',store.getState())
        // );
    
        useEffect(()=>{
          
          
            store.subscribe(()=>{
          
          
                console.log('订阅更新,打印2-----',store.getState());
                setCount(store.getState());
            });
        });
    
    
        return(
            <div>
                当前数字是:{
          
          count}    &nbsp;&nbsp;&nbsp;&nbsp;
                当前数字是:{
          
          store.getState()}  
                <br /><br />
    
                <button onClick={
          
          add}>点我 +1</button> <br /><br />
                <button onClick={
          
          subtract}>点我 -1</button>
            </div>
        )
    }
    
    export default CountNumRedux;
    

Guess you like

Origin blog.csdn.net/suixinfeixiangfei/article/details/133072426