React教程18 – Redux
这个教程将会交给你如何在React 应用中实践Flux原理。 我们这里使用 Redux 框架。这篇教程的目的就是通过一个简单的例子让你理解 Redux 和 React。
第1步 – 安装 Redux
通过npm命令安装react-redux
C:\Users\username\Desktop\reactApp>npm install --save react-redux
第2步 – 创建相应目录和文件
这一步我们创建 actions, reducers 和 components 相对应的目录。这是目录结构示意图。
第3步 – Actions
Actions 是使用type 属性来告知数据需要发送到store中的 JavaScript 对象。我们这里定义 ADD_TODO action 用来添加元素到list中。 addTodo function 是 action 的创建者,返回,并给每一个新增元素添加 id 。
actions/actions.js
export const ADD_TODO = 'ADD_TODO' let nextTodoId = 0; export function addTodo(text) { return { type: ADD_TODO, id: nextTodoId++, text }; }
第4步 – Reducers
Actions 只是触发app中的变化, 而 reducers 具体定义怎样变化。我们这里使用 switch 语句来搜索 ADD_TODO action。 reducer function 接受 state 和 action 来计算,返回更新的state。 第一个 function 用来创建新的list item, 第二个function把item push到list中。
最后我们使用 combineReducers helper function 来添加新的reducers。
reducers/reducers.js
import { combineReducers } from 'redux' import { ADD_TODO } from '../actions/actions' function todo(state, action) { switch (action.type) { case ADD_TODO: return { id: action.id, text: action.text, } default: return state } } function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ ...state, todo(undefined, action) ] default: return state } } const todoApp = combineReducers({ todos }) export default todoApp
第5步 – Store
Store 是存储 app的 state 的地方。有了 reducers后,就很容易创建store。我们这里把store的property 传到用来装route component的 provider component中。
main.js
import React from 'react' import { render } from 'react-dom' import { createStore } from 'redux' import { Provider } from 'react-redux' import App from './App.jsx' import todoApp from './reducers/reducers' let store = createStore(todoApp) let rootElement = document.getElementById('app') render( <Provider store = {store}> <App /> </Provider>, rootElement )
第6步 – 根组件Root Component
App component是app的root component 。只有 root component 需要特别处理redux。这里最需要注意的是 connect function,用来链接我们的 root component App 和 store。这个function 加入 select function 作为一个argument。 select function 拿到来自store的state,并返回在其他component中可以用到的 props (visibleTodos)。
App.js
import React, { Component } from 'react' import { connect } from 'react-redux' import { addTodo } from './actions/actions' import AddTodo from './components/AddTodo.jsx' import TodoList from './components/TodoList.jsx' class App extends Component { render() { const { dispatch, visibleTodos } = this.props return ( <div> <AddTodo onAddClick = {text ⇒ dispatch(addTodo(text))} /> <TodoList todos = {visibleTodos}/> </div> ) } } function select(state) { return { visibleTodos: state.todos } } export default connect(select)(App)
第7步 – 其他Components
这些组件不需要为 redux 做特别处理。
components/AddTodo.js
import React, { Component, PropTypes } from 'react' export default class AddTodo extends Component { render() { return ( <div> <input type = 'text' ref = 'input' /> <button onClick = {(e) ⇒ this.handleClick(e)}> Add </button> </div> ) } handleClick(e) { const node = this.refs.input const text = node.value.trim() this.props.onAddClick(text) node.value = '' } }
components/Todo.js
import React, { Component, PropTypes } from 'react' export default class Todo extends Component { render() { return ( <li> {this.props.text} </li> ) } }
components/TodoList.js
import React, { Component, PropTypes } from 'react' import Todo from './Todo.jsx' export default class TodoList extends Component { render() { return ( <ul> {this.props.todos.map(todo ⇒ <Todo key = {todo.id} {...todo} /> )} </ul> ) } } 现在启动app,就可以添加item到list中了。
