Redux 学习总结 (React)

40次阅读

共计 3590 个字符,预计需要花费 9 分钟才能阅读完成。

在 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 创建函数的库(对减少样板代码有帮助):

redux-actions
redux-act

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
redux-saga

redux-thunk
通过使用指定的 middleware,action 创建函数除了返回 action 对象外还可以返回函数。这时,这个 action 创建函数就成为了 thunk。
路由跳转(react-router)
参考资料:

Redux 中文文档
React Native Training

正文完
 0