要将 Redux 和 React 结合起来使用,就还需要一些额外的库,其中最重要的是 react-redux
react-redux 提供了两个重要的对象,Provider 和 connect,前者使 React 组件可被连接(connectable),后者把 React 组件和 Redux 的 store 真正连接起来
本章节将介绍如何实现 Flux模式。 我们使用 Redux 类库,然后一步一步的把 Redux 和 React 组合在一起
第一步 - 安装 Redux
安装 Redux 的命令如下
npm install --save react-redux
第二步 - 生成项目目录和文件
创建目录结构和相应的文件
第三步 - Actions
Action 是纯声明式的数据结构,只提供事件的所有要素,不提供逻辑。
actions/actions.js
export const ADD_TODO = 'ADD_TODO'
let nextTodoId = 0;
export function addTodo(text) {
return {
type: ADD_TODO,
id: nextTodoId++,
text
};
}
第四步 - Reducers
reducer 是一个匹配函数,action的发送是全局的:所有的reducer都可以捕捉到并匹配与自己相关与否,相关就拿走action中的要素进行逻辑处理,修改store中的状态,不相关就不对state做处理原样返回
reducers 作为事件处理函数,它接收 state 和 action 作为参数,进行一系列的计算,然后返回计算后的 state
在本范例中,我们定义了两个函数,todo 用来添加待办事项, todos 用来生成列表。
帮助函数 combineReducers 方便管理和添加 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
Step 5 - Store
Redux 的 store 用来管理 React 应用的所有状态(state)。 可以简单的使用 createStore 创建一个 store ,然后把它赋值给 provider 的 store属性就可以完成 store 和 provider的绑定
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 - App Component
App 组件是应用程序的入口组件,只有 App 组件能被 redux 唤醒。 其中 connect 函数是最重要的部分,他把 App 组件连接到 Redux 的 store。
connect 使用 select 作为参数,而 select 函数从 Redux 的 store 中提取 state 数据,然后注入 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)
Step 7 - Other Components
下面这些组件不会被 Redux 唤醒 也就是说,下面这些组件和 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,添加一个 待办事项 试一试吧