Redux 之 react 结合 redux 实战篇

发布于 2024-11-19 17:54:13 字数 6732 浏览 0 评论 0

TODO 为例分析,实际开发中并不是那么简单,下面的原型只是开发中的一个原型,这个简单的例子,有助于掌握数据处理传递的原则。

一、定义 constants

这一步不是必须的

/**
* 常量统一保存,便于管理
*/
export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO';
export const SET_VISIBILITY = 'SET_VISIBILITY';

//controll todo wheher show or hide
export const SHOW_ALL = 'SHOW_ALL';
export const SHOW_ACTIVE = 'SHOW_ACTIVE';
export const SHOW_COMPLETED = 'SHOW_COMPLETED';

二、定义 actionCreator

/**
* 定义 action creator
*/

import * as actionType from '../constant/index';

let nextTodo = 0;

export const addTodo = (text)=>({
type:actionType.ADD_TODO,
id:nextTodo++,
text
})

export const toggleTodo = (id)=>({
type:actionType.TOGGLE_TODO,
id
})

export const setVisibilityFilter = (filter)=>{
return {
type:actionType.SET_VISIBILITY,
filter
}
}

三、定义 reducer

拆分 reducer

  • SetVisibility.js
/**
* 处理 TODO 可见与不可见的 reducer
*/
import * as actionType from '../constant/index';

// 初始状态是自己设置的 后面的状态会转化
// 接收当前状态(设置默认的过滤 SHOW_ALL,如设置某些选项卡的 active 一样),和 action 返回新的 state
export const visibilityFilter = (state='SHOW_ALL',action)=>{
switch(action.type) {
case actionType.SET_VISIBILITY:
return action.filter;
default:
return state;
}
}
  • addTodo.js
/**
* 定义处理 action 的 reducers
*/
import * as actionType from '../constant/index';

//传入当前的状态空数、action
export const todos = (state = [],action)=>{
switch(action.type){ // 匹配用户触发的 actionType
case actionType.ADD_TODO:
// 合并上一次的状态和当前的状态 返回 todos 数组
return [
...state,//把数组展开合并
{
id:action.id,
text:action.text,
completed:false//用户控制 TODO 是否处于点击完成的状态 默认 false 没点击
}
]
// TODO 列表来回切换 遍历 add_todo 返回的数组 通过 completed 来判断
case actionType.TOGGLE_TODO:
return state.map(todo=>(todo.id===action.id)?{...todo,completed:!todo.completed}:todo)
default:
return state;//匹配不到返回 state
}
}

合并 reducer

/**
* 合并 reducers
*/

import { combineReducers } from 'redux'
import {todos} from './addTodo';
import {visibilityFilter} from './SetVisibility';

export default combineReducers({
todos, //这些键其实就是被拆分的状态,后面在容器组件中需要通过 connect 链接
visibilityFilter
});

四、定义 store

import { applyMiddleware, createStore } from 'redux';
import reducer from '../reducers/index';
import logger from 'redux-logger';

// 创建 store 用来存储状态
export const store = createStore(
reducer,
applyMiddleware(logger) //处理日志中间件
)

五、结合 react-redux

这里忽略展示组件,完成源码看文章结尾

  • 首先我们在 container 组件中处理好之前分解合并的那些 reducer 的键,然后在通过 connect 链接,传递给展示组件的属性使用

容器组件处理

react-todos/src/container/FilterLink.js

// 处理数组过滤

import { connect } from 'react-redux';
import Link from '../components/Link';
import { setVisibilityFilter } from '../actions/index';

// 这里的 ownProps 指的是 FilterLink
// 这里的 state 其实就是之前分解的 todos,visibilityFilter
const mapStateToProps = (state, ownProps) => {
return {
active:ownProps.filter === state.visibilityFilter
}
}

/**
如果 mapDispatchToProps 是一个函数,会得到 dispatch 和 ownProps(容器组件的 props 对象)两个参数。
*/
const mapDispatchToProps = (dispatch, ownProps) => ({
// 这里处理对应的事件,传递给展示组件的属性
onClick: () => {
dispatch(setVisibilityFilter(ownProps.filter))
}
})

export default connect(
mapStateToProps,
mapDispatchToProps
)(Link);
  • 分析
    • 这里通过 connect 组件把之前 reducer 处理的那些状态链接

export default combineReducers({
todos, //这些键其实就是被拆分的状态,后面在容器组件中需要通过 connect 链接
visibilityFilter
});

react-todos/src/container/VisibilityTodoList.js

/**
* 处理可见于不可见组件的逻辑
*/
import {connect} from 'react-redux';
import TodoList from '../components/TodoList';
import {toggleTodo} from '../actions/index';
import * as actionType from '../constant/index';
console.log(toggleTodo)

// todos 是返回的数组,filter 是过滤的选项如 SHOW_ALL SHOW_ACTIVE.
const getVisibilityTodos = (todos,filter)=>{
switch(filter) {
case actionType.SHOW_ALL:
return todos;
case actionType.SHOW_ACTIVE:
return todos.filter(t => !t.completed);
case actionType.SHOW_COMPLETED:
return todos.filter(t => t.completed);
default:
throw new Error('未知的'+filter);
}
}

// 把状态转化为展示组件的属性转递过去
/**
*
* @param {*} state 也就是
* export default CombineReducers({
Todos,
SetVisibility
*});
* @param {*} ownProps 返回的容器组件本身的参数 如<Filter name="poetries">此时的 ownProps 就是 name 了
*/

const mapStateToProps = (state) => {
return {
todos: getVisibilityTodos(state.todos,state.visibilityFilter),
count:state.todos.length
}
}

/**
* 如果 mapDispatchToProps 是一个对象,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出
*/
const mapDispatchToProps = {
onTodoClick: toggleTodo
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)

react-todos/src/container/addTodos.js

/**
* Addtodo 的处逻辑
*/
import React, { Component } from 'react';
import {addTodo} from '../actions/index';
import AddTask from '../components/addTodo';
import {connect} from 'react-redux';

const mapStateToProps = (state, ownProps) => ({

})

const mapDispatchToProps = {
addTodo:addTodo
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(AddTask);

到此分析完毕,展示组件就不分析了,展示组件本身是没有数据的,需要 container 处理传递

完整的源码

https://github.com/poetries/react-todos

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

微暖i

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

有深☉意

文章 0 评论 0

硪扪都還晓

文章 0 评论 0

DS

文章 0 评论 0

我也只是我

文章 0 评论 0

TangBin

文章 0 评论 0

橪书

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文