一步一步用 React Redux 编写一个 Todo App

原文地址: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"
)

我的感想:这个教程是我目前见到的最详细,写的最好的教程,因为它把每一步怎么做,思路都写出来了,受益良多,因此翻译出来。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容