以TODO
为例分析,实际开发中并不是那么简单,下面的原型只是开发中的一个原型,这个简单的例子,有助于掌握数据处理传递的原则。
一、定义constants
这一步不是必须的
1 2 3 4 5 6 7 8 9 10 11
|
export const ADD_TODO = 'ADD_TODO'; export const TOGGLE_TODO = 'TOGGLE_TODO'; export const SET_VISIBILITY = 'SET_VISIBILITY';
export const SHOW_ALL = 'SHOW_ALL'; export const SHOW_ACTIVE = 'SHOW_ACTIVE'; export const SHOW_COMPLETED = 'SHOW_COMPLETED';
|
二、定义actionCreator
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
|
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
import * as actionType from '../constant/index';
export const visibilityFilter = (state='SHOW_ALL',action)=>{ switch(action.type) { case actionType.SET_VISIBILITY: return action.filter; default: return state; } }
|
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
|
import * as actionType from '../constant/index';
export const todos = (state = [],action)=>{ switch(action.type){ case actionType.ADD_TODO: return [ ...state, { id:action.id, text:action.text, completed:false } ] case actionType.TOGGLE_TODO: return state.map(todo=>(todo.id===action.id)?{...todo,completed:!todo.completed}:todo) default: return state; } }
|
合并reducer
1 2 3 4 5 6 7 8 9 10 11 12
|
import { combineReducers } from 'redux' import {todos} from './addTodo'; import {visibilityFilter} from './SetVisibility';
export default combineReducers({ todos, visibilityFilter });
|
四、定义store
1 2 3 4 5 6 7 8 9
| import { applyMiddleware, createStore } from 'redux'; import reducer from '../reducers/index'; import logger from 'redux-logger';
export const store = createStore( reducer, applyMiddleware(logger) )
|
五、结合react-redux
这里忽略展示组件,完成源码看文章结尾
- 首先我们在
container
组件中处理好之前分解合并的那些reducer
的键,然后在通过connect
链接,传递给展示组件的属性使用
容器组件处理
react-todos/src/container/FilterLink.js
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
|
import { connect } from 'react-redux'; import Link from '../components/Link'; import { setVisibilityFilter } from '../actions/index';
const mapStateToProps = (state, ownProps) => { return { active:ownProps.filter === state.visibilityFilter } }
const mapDispatchToProps = (dispatch, ownProps) => ({
onClick: () => { dispatch(setVisibilityFilter(ownProps.filter)) } })
export default connect( mapStateToProps, mapDispatchToProps )(Link);
|
- 分析
- 这里通过
connect
组件把之前reducer
处理的那些状态链接
1 2 3 4 5
| export default combineReducers({ todos, visibilityFilter });
|
react-todos/src/container/VisibilityTodoList.js
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
|
import {connect} from 'react-redux'; import TodoList from '../components/TodoList'; import {toggleTodo} from '../actions/index'; import * as actionType from '../constant/index'; console.log(toggleTodo)
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); } }
const mapStateToProps = (state) => { return { todos: getVisibilityTodos(state.todos,state.visibilityFilter), count:state.todos.length } }
const mapDispatchToProps = { onTodoClick: toggleTodo }
export default connect( mapStateToProps, mapDispatchToProps )(TodoList)
|
react-todos/src/container/addTodos.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
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