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

10 篇文章 0 订阅
9 篇文章 0 订阅

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'
    })
    

注意: 当实用全局注入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;

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 } 
});

三、在组件中具体使用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;
  }
};

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值