• react-redux 实现 todolist (联系上一篇文章)


    redux的原理

    1. 创建store,全局通过Provider注入
    2. reducer实现初始化数据,多个reducer使用combineReducers, 将合并为一个数据对象
    3. reducer(prevState, action) 根据action的值,间接更新state;
    4. action定义为一个函数可以接受参数,并对参数进行处理
      const add = val => ({
          type: 'ADD_TODO',
          payload: {
         	 id: 33,
         	 content: 'xxx'
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    注意: 当实用全局注入store后,则可以在任意地方获取store参数。

    具体实践如下:
    一、store

    1.  创建store
    import { createStore } from "redux";
    import reducer from "./reducers/index";
    export default createStore(reducer);
    
    2. 数据初始化
    import { combineReducers } from "redux";
    // 使用两个reducer
    import visibilityFilter from "./visibilityFilter";
    import todos from "./todos";
    
    export default combineReducers({ todos, visibilityFilter });
    
    //  (1) todos
    import { ADD_TODO, TOGGLE_TODO } from "../actions/actionTypes"  // 自定义action类型
    const initialState = {
      allIds: [],
      byIds: {}
    };
    
    // eslint-disable-next-line
    export default function(state = initialState, action) {
      switch (action.type) {
        case ADD_TODO: {
          const { id, content } = action.payload;
          return {      // 只可以对state间接操作,返回一个新的对象
            ...state,
            allIds: [...state.allIds, id],
            byIds: {
              ...state.byIds,
              [id]: {
                content,
                completed: false
              }
            }
          };
        }
        case TOGGLE_TODO: {
          const { id } = action.payload;
          return {
            ...state,
            byIds: {
              ...state.byIds,
              [id]: {
                ...state.byIds[id],
                completed: !state.byIds[id].completed
              }
            }
          };
        }
        default:
          return state;
      }
    }
    //  (2) visibilityFilter
    import { SET_FILTER } from "../actions/actionTypes"
    import { VISIBILITY_FILTERS } from "../../static/VisibilityFilters";
    
    const initialState = VISIBILITY_FILTERS.ALL;
    
    const visibilityFilter = (state = initialState, action) => {
      switch (action.type) {
        case SET_FILTER: {
          return action.payload.filter;
        }
        default: {
          return state;
        }
      }
    };
    
    export default visibilityFilter;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    store中的数据为: {allId: [], byId: {}, visibilityFilter:'all'}

    二、 actions

    
    import {ADD_TODO, TOGGLE_TODO, SET_FILTER} from './actionTypes'
    
    let count = 0; // 全局的计数变量
    
    export const addToDo = content => ({
        type: ADD_TODO,
        payload: {
            id: ++count,
            content
        }
    })
    
    
    export const toggleTodo = id => ({
        type: TOGGLE_TODO,
        payload: {id}
    })
    
    
    export const setFilter = filter => ({ 
        type: SET_FILTER, 
        payload: { filter } 
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    三、在组件中具体使用connect
    connect(mapStateToProps, mapDispatchToProps)(Component)

    1
    import React from 'react'
    import { useState } from 'react';
    
    import { connect } from "react-redux";
    import { addToDo } from "../store/actions/actions"
    
    function AddTodo({ addToDo }) {
        const [input, setInput] = useState('')
    
        const updateInput = input => {
            setInput(input)
        };
    
        const handleAddTodo = () => {
            addToDo(input);
            setInput('');
        };
    
    
        return (
            <div>
                <input
                    onChange={e => updateInput(e.target.value)}
                    value={input}
                />
                <button className="add-todo" onClick={handleAddTodo}>
                    Add Todo
                </button>
            </div>
        );
    }
    
    export default connect(null, { addToDo })(AddTodo) 
    // addToDo为action, AddTodo为组件2
    import React from "react";
    import { connect } from "react-redux";
    import { setFilter } from "../store/actions/actions";
    import { VISIBILITY_FILTERS } from "../static/VisibilityFilters"
    
    const Filter = ({ activeFilter, setFilter }) => {
      return (
        <div className="visibility-filters">
          {Object.keys(VISIBILITY_FILTERS).map((filterKey) => {
            const currentFilter = VISIBILITY_FILTERS[filterKey];
            return (
              <span
                key={`visibility-filter-${currentFilter}`}
                className={cx(
                  "filter",
                  currentFilter === activeFilter && "filter--active"
                )}
                onClick={() => {
                  setFilter(currentFilter);
                }}
              >
                {currentFilter}
              </span>
            );
          })}
        </div>
      );
    };
    
    const mapStateToProps = (state) => {
      return { activeFilter: state.visibilityFilter };
    };
    
    // const mapDispatchToProps = (dispatch) => {
    //   return {
    //     handle() {
    //       dispatch(setFilter)
    //     }
    //   }
    // }
    export default connect(mapStateToProps, { setFilter })(Filter);3: 补充一个获取todos的方法
    import React from "react";
    import { connect } from "react-redux";
    import Todo from "./Todo";
    import { getTodosByVisibilityFilter } from  "../store/selectors"
    
    const TodoList = ({ todos }) => (
      <ul className="todo-list">
        {todos && todos.length
          ? todos.map((todo) => {
              return <Todo key={`todo-${todo.id}`} todo={todo} />;
            })
          : "No todos, yay!"}
      </ul>
    );
    
    
    const mapStateToProps = (state) => {
      const { visibilityFilter } = state; // 初始值为all
      const todos = getTodosByVisibilityFilter(state, visibilityFilter);
      return { todos };
    }
    
    
    export default connect(mapStateToProps)(TodoList);
    
    // selector.js中通过store获取合成后的list数组
    
    import { VISIBILITY_FILTERS } from "../static/VisibilityFilters";
    
    const getTodosState = store => store.todos;  // allIds, byIds, visibilityFilter
    
    const getTodoList = store =>
      getTodosState(store) ? getTodosState(store).allIds : []; // allIds
    
    const getTodoById = (store, id) =>
      getTodosState(store) ? { ...getTodosState(store).byIds[id], id } : {}; // {content, completed, id}
    
    const getTodos = store =>  // 映射list [{content, completed, id},....]
      getTodoList(store).map(id => getTodoById(store, id));
    
    
    export const getTodosByVisibilityFilter = (store, visibilityFilter) => {  
    // 分类筛选, 此时store已经可以完全获取了
      const allTodos = getTodos(store);
      switch (visibilityFilter) {
        case VISIBILITY_FILTERS.COMPLETED:
          return allTodos.filter(todo => todo.completed);
        case VISIBILITY_FILTERS.INCOMPLETE:
          return allTodos.filter(todo => !todo.completed);
        case VISIBILITY_FILTERS.ALL:
        default:
          return allTodos;
      }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136

    **最后代码 (很简洁!!) **

    import React from 'react'
    import AddTodo from './AddTodo'
    import Todolist from './TodoList';
    import Filter from './Filter';
    
    export default function TodoApp() {
      return (
        <>
          <h1>this is Todo List test!!!!</h1>
          <AddTodo/>
          <Todolist/>
          <Filter/>
        </>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    基本的思想和代码都如上所示,总结如下:

    1. 多组件使用的变量放在store中,也可以分模块定义,最后组合为一个对象;
    2. 操作state时,传参进入action,定义对象{type: '', payload: ....}, 保存数据;
    3. 组件连接store啦, connect(state, {action})(component), 使用props即可接收;
    4. reducer根据state和action,更新state操作,不能直接修改,返回一个新的对象(利用扩展运算符); (搞定了)

    后文: 接下来打算做个后台管理系统,巩固下知识!!!加油

  • 相关阅读:
    【跨模态】【对比学习】CLIP:文本监督CV的预训练(2021)
    SpringCLoud——RabbitMQ的消息模型
    MNIST字符识别(C++)
    Centos安装mongodb
    基于RFID技术的烟草供应链数字化管理方案
    如何为你的项目选择LoRa模块?
    Docker:容器网络互联
    C++学习day2
    [ Windows-Nginx ]Windows服务器,Tomcat容器部署项目,整合Nginx
    Eslint配置
  • 原文地址:https://blog.csdn.net/qq_33404590/article/details/126272481