内容简介:在 React 的学习和开发中,如果 state (状态)变得复杂时(例如一个状态需要能够在多个 view 中使用和更新),使用 Redux 可以有效地管理 state,使 state tree 结构清晰,方便状态的更新和使用。当然,Redux 和 React 并没有什么关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。只是对我来说目前主要需要在 React 中使用,所以在这里和 React 联系起来便于理解记忆。
在 React 的学习和开发中,如果 state (状态)变得复杂时(例如一个状态需要能够在多个 view 中使用和更新),使用 Redux 可以有效地管理 state,使 state tree 结构清晰,方便状态的更新和使用。
当然,Redux 和 React 并没有什么关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。只是对我来说目前主要需要在 React 中使用,所以在这里和 React 联系起来便于理解记忆。
数据流
Action
只是描述 state (状态)更新的动作,即“发生了什么”,并不更新 state。
const ADD_TODO = 'ADD_TODO'
{
type: ADD_TODO,
text: 'Build my first Redux app'
}
- type:必填,表示将要执行的动作,通常会被定义成字符串常量,尤其是大型项目。
- 除了 type 外的其他字段:可选,自定义,通常可传相关参数。例如上面例子中的 text。
Action 创建函数
简单返回一个 Action:
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
dispatch Action:
dispatch(addTodo(text)) // 或者创建一个 被绑定的 action 创建函数 来自动 dispatch const boundAddTodo = text => dispatch(addTodo(text)) boundAddTodo(text)
帮助生成 Action 创建函数的库(对减少样板代码有帮助):
Reducer
说明在发起 action 后 state 应该如何更新。
是一个纯函数:只要传入参数相同,返回计算得到的下一个 state 就一定相同。
(previousState, action) => newState
注意,不能在 reducer 中执行的操作:
- 修改传入的参数
- 执行有副作用的操作,如 API 请求和路由跳转
- 调用非纯函数,如 Date.now() 或 Math.random()
import { combineReducers } from 'redux'
import {
ADD_TODO,
TOGGLE_TODO,
SET_VISIBILITY_FILTER,
VisibilityFilters
} from './actions'
const { SHOW_ALL } = VisibilityFilters
function visibilityFilter(state = SHOW_ALL, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter
default:
return state
}
}
function todos(state = [], action) {
switch (action.type) {
case ADD_TODO:
return [
...state,
{
text: action.text,
completed: false
}
]
case TOGGLE_TODO:
return state.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
completed: !todo.completed
})
}
return todo
})
default:
return state
}
}
const todoApp = combineReducers({
visibilityFilter,
todos
})
export default todoApp
Store
Redux 应用只有一个单一的 store。
- 维持应用的 state;
- 提供 getState() 方法获取 state;
- 提供 dispatch(action) 方法更新 state;
- 通过 subscribe(listener) 注册监听器;
- 通过 subscribe(listener) 返回的函数注销监听器。
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(
todoApp,
[preloadedState], // 可选,state 初始状态
enhancer
)
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import DevTools from './containers/DevTools'
import reducer from '../reducers/index'
export default function configureStore() {
const store = createStore(
reducer,
compose(
applyMiddleware(thunk),
DevTools.instrument()
)
);
return store;
}
react-redux
connect() 方法( mapStateToProps 、 mapDispatchToProps )
替代 store.subscribe() ,从 Redux state 树中读取部分数据,并通过 props 提供给要渲染的组件。
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actions from './actions';
class App extends Component {
handleAddTodo = () => {
const { actions } = this.props;
actions.addTodo('Create a new todo');
}
render() {
const { todos } = this.props;
return (
<div>
<Button onClick={this.handleAddTodo}>+</Button>
<ul>
{todos.map(todo => (
<Todo key={todo.id} {...todo} />
))}
</ul>
</div>
);
}
}
function mapStateToProps(state) {
return {
todos: state.todos
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
addTodo: actions.addTodo
}, dispatch)
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);
Provider 组件
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import configureStore from './store/configureStore'
import App from './components/App'
render(
<Provider store={configureStore()}>
<App />
</Provider>,
document.getElementById('root')
API 请求
一般情况下,每个 API 请求都需要 dispatch 至少三种 action:
- 通知 reducer 请求开始的 action
{ type: 'FETCH_POSTS_REQUEST' }
reducer 可能会{...state, isFetching: true} - 一种通知 reducer 请求成功的 action
{ type: 'FETCH_POSTS_SUCCESS', response: { ... } }
reducer 可能会{...state, isFetching: false, data: action.response} - 一种通知 reducer 请求失败的 action
{ type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
reducer 可能会{...state, isFetching: false, error: action.error}
使用 middleware 中间件实现网络请求:
redux-thunk
通过使用指定的 middleware,action 创建函数除了返回 action 对象外还可以返回函数。这时,这个 action 创建函数就成为了 thunk。
路由跳转( react-router )
参考资料:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Web开发从初学到精通
方振宇 / 电子工业 / 2010-6 / 69.00元
《Java Web开发从初学到精通》介绍如何整合Web框架进行J2EE开发,所有实例都基于MyEclipse IDE开发,引领读者快速进入基于JaVa web的J2EE应用领域。《Java Web开发从初学到精通》开始主要介绍Servlet、JSP、JavaBean、EL、JSTL、JDBC等Web开发基础知识,然后学习Struts、Hibernate、Spring、Ajax、JSF等开源框架,并......一起来看看 《Java Web开发从初学到精通》 这本书的介绍吧!