原文地址:Step by Step Guide To Building React Redux Apps
项目地址:react-redux-todoApp / redux
第一步: 对 App 做一个详细的模拟
模拟应该包括数据和虚拟效果(比如 todo 条目的删除线,或者过滤器选中 “All” 时,不应该显示链接的下划线)。
注意: 你可以点击下面的图片放大或者缩小。
便签纸上的内容为:
步骤一: 对每个屏幕都做一个模拟
如何做:
1.尽可能地详细
2.保证所有的数据和虚拟的效果(比如 todo 条目的删除线)
第二步:将 App 分成几个部分
根据整体的“目的”,尝试将 App 拆分成块。
我们将 todo App 拆分成三块: “AddTodo”、“TodoList”、“Filter”。
便签纸上的内容为:
步骤二:将 App 拆分成块
如何做:基于整个目的将他们分拆,这是一个 App 常用的粗略的方法和大致的块。
我们的 Todo App 有三个主要目的:
1.添加一个新的 Todo 条目(AddTodo component)
2.展示 Todo 条目的列表(TodoList component)
3.展示过滤的 Todo 条目(Filter component)
Redux 术语: “Action” 和 “State”
每个 component 都需要做两件事情:
1,基于数据渲染 DOM,这些数据称为“state”。
2.监听用户和其他事件,并且将它们传给 JS 函数。这些叫做“Action”。
第三步:每个 “ Component” 列表的 “state” 和 “Action”
仔细看第二步的每个部分,并且列出它们的 “State” 和 “Action”。
我们有三个部分:“AddTodo”, “TodoList”, “Filter” ,让我们来分别列出它们各自的 “Action” 和 “State”。
3.1 AddTodo Component 的 “State” 和 “Action”
在这个部分,没有 “state”,因为这个部分看起来没有基于任何数据的改变,但是它需要其他部分知道用户什么时候创建了一个新的 todo,我们把这个 “action” 叫做 “ADD_TODO”。
便签纸上的内容为:
AddTodo component
state:
这是一个简单的区域,展示它不需要基于任何的数据。
Actions(Events)
AddTodo component 允许我们创建一个新的 todo 条目,通过监听 DOM 的事件,并从输入框重新渲染数据。
在这个例子中,我们可以通过创建一个 JSON 对象来描述这个 AddTodo action ,并且像下面这样添加数据:
{
type: "ADD_TODO"
payload: {data: "Learn Redux", id:"1", completed: false}
}
3.2 TodoList Component 的 State 和 Actions
TodoList component 需要一个 Todo 条目的新的数组去渲染它自己,所以它需要一个 state,我们叫它 Todos(数组)。同时也需要知道选择某个 “Filter” 时,哪个 Todo 条目需要展示, 这需要另外一个 state,我们叫它 “VisibilityFilter”(布尔)。
另外,还需要允许我们能够转换 Todo 条目的状态,使其完成或者没有完成。我们需要让其他组件知道我们转换的操作。我们把这个 action 称为 “TOGGLE_TODO”。
3.3 Filter Component 的 State 和 Actions
Filter 组件基于是否是 active 的一个链接或者是简单文本来渲染。我们称这个 state 为 “CurrentFilter”。
Filter 组件也需要让其他组件知道用户什么时候点击了它,这个 action 称为“SET_VIBILITY_FILTER”。
Redux 术语:Action Creators
Action Creators 是一些简单的函数,它的作用就是从 DOM 事件中数据,它是一个 JSON 格式的 “Action” 对象并且返回这个对象(又称为 “Action”)。这可以帮助我们将 data/payload 形式化。
另外,它允许任何其他的组件将这些 actions 传递(又称为 dispatch)给其他组件。
第四步:为每个 Action 创建 Action Creators
我们总共又三个 actions: ADD_TODO, TOGGLE_TODO,SET_VISIBILITY_FILTER。让我们为它们每个创建 create actions。
//1. Takes the text from AddTodo field and returns proper “Action” JSON to send to other components.
export const addTodo = (text) => {
return {
type: ‘ADD_TODO’,
id: nextTodoId++,
text, //<--ES6. same as text:text, in ES5
completed: false //<-- initially this is set to false
}
}
//2. Takes filter string and returns proper “Action” JSON object to send to other components.
export const setVisibilityFilter = (filter) => {
return {
type: ‘SET_VISIBILITY_FILTER’,
filter
}
}
//3. Takes Todo item’s id and returns proper “Action” JSON object to send to other components.
export const toggleTodo = (id) => {
return {
type: ‘TOGGLE_TODO’,
id
}
}
Redux 术语: Reducers
Reducers 是一些函数,它接收从 Redux 传来的 “state” 和 “action” JSON 对象。并且返回一个新的 “state”,存储回 Redux 中。
1.Reducer 函数称为 “Container”,当用户触发了 “action”。
2.如果 reducer 改变了 state, Redux 传递一个新的 state 给每个组件,并且重新渲染组件。
For example the below function takes Redux’ state(an array of previous todos), and returns a **new** array of todos(new state) w/ the new Todo added if action’s type is “ADD_TODO”.
const todo = (state = [], action) => {
switch (action.type) {
case ‘ADD_TODO’:
return
[…state,{id: action.id, text: action.text, completed:false}];
}
第五步:为每一个 Action 写 Reducers
为了简化教程,只展示其中一个。
const todo = (state, action) => {
switch (action.type) {
case ‘ADD_TODO’:
return […state,{id: action.id, text: action.text,
completed:false}]
case ‘TOGGLE_TODO’:
return state.map(todo =>
if (todo.id !== action.id) {
return todo
}
return Object.assign({},
todo, {completed: !todo.completed})
)
case ‘SET_VISIBILITY_FILTER’: {
return action.filter
}
default:
return state
}
}
Redux 术语: “Presentational” 和 “Container” 组件
保持每个组件中 React 和 Redux 的内在逻辑可能会混乱,所以 Redux 提倡创建一个展示组件(Presentational)——仅供展示数据,和一个父容器组件(Container)——包含Redux,发送“Actions”或更多功能。
父容器组件传递数据给展示组件,控制事件,处理展示组件中的 React。
图例: 黄色虚线 = 展示组件,黑色虚线=容器组件
第六步: 完善每个展示组件
6.1 完善 AddTodoForm 的展示组件
6.2 完善 TodoList 展示组件
6.3 完善 Link 展示组件
第七步: 为每个展示组件创建容器组件
7.1 创建容器组件——AddTodo
7.2 创建容器组件——TodoList
7.3创建容器组件——Filter
第八步: 将它们合在一起
import React from ‘react’ // ← Main React library
import { render } from ‘react-dom’ // ← Main react library
import { Provider } from ‘react-redux’ //← Bridge React and Redux
import { createStore } from ‘redux’ // ← Main Redux library
import todoApp from ‘./reducers’ // ← List of Reducers we created
//Import all components we created earlier
import AddTodo from ‘../containers/AddTodo’
import VisibleTodoList from ‘../containers/VisibleTodoList’
import Footer from ‘./Footer’ // ← This is a presentational component that contains 3 FilterLink Container comp
//Create Redux Store by passing it the reducers we created earlier.
let store = createStore(reducers)
render(
<Provider store={store}> ← The Provider component from react-redux injects the store to all the child components
<div>
<AddTodo />
<VisibleTodoList />
<Footer />
</div>
</Provider>,
document.getElementById(‘root’) //<-- Render to a div w/ id "root"
)
我的感想:这个教程是我目前见到的最详细,写的最好的教程,因为它把每一步怎么做,思路都写出来了,受益良多,因此翻译出来。