Redux 简介
Redux
概念
redux react-redux
const 文件
action
aciton creator
reducer
store
state
dispatch
combineReducers
connect
mapStateToProps
mapDispatchToProps
middleware
store
保存数据的一个单一状态树
要通过 createStore 方法生成
import {createStore} from 'redux'
const store = createStore(fn)
action
Action 是一个对象。其中的 type 属性是必须的,表示 Action 的名称。
其他属性可以自由设置。
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
}
action creator
每次手写 action 很麻烦,于是要定义一个函数来生成 action,该函数就是
action creator
const chooseNav = (index) => {
return {
type: CHOOSE_NAV,
index
}
}
const action = chooseNav(1)
store.dispatch
要触发 action,就要使用 store.dispatch
import { createStore } from 'redux';
const store = createStore(fn)
store.dispatch({
type: 'ADD_TODO',
payload: 'Learn Redux'
})
const 文件
将 action.type 定义为常量
reducer 通过 action.type 判断是哪个 action
reducer
更新数据, 返回新的 state
const initState = {
}
const reducer = (state = initState, action) => {
switch(action.type) {
case xxx:
xxx
break
case yyy:
yyy
break
default
return state
}
}
combineReducers
合并多个 reducer
import { combineReducers } from 'redux'
const chatReducer = combineReducers({
chatLog,
statusMessage,
userName
})
export default chatReducer
创建 stroe
import chatReducer from './xxx'
const store = createStore(
chatReducer
)
export default store
Provider
store 添加在 Provider 组件
import store from './yyy'
import {Provider} from 'react-redux'
ReactDOM.render(
< Provider store={store} >
...
< /Provider >,
document.getElementById('root'))
在组件中使用
mapStateToProps 传 props 给组件
mapDispatchToProps 传 dispatch 方法 给组件
通过 connect 传个组件
例子
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import CommentList from '../components/CommentList.js'
import { initComments, deleteComment} from '../reducers/comments.js'
import {connect} from 'react-redux'
class CommentListContainer extends Component {
static propTypes = {
comments: PropTypes.array,
initComments: PropTypes.func,
deleteComment: PropTypes.func
}
componentWillMount() {
this._loadComments()
}
_loadComments() {
let comments = localStorage.getItem('comments')
comments = comments ? JSON.parse(comments) : []
this.props.initComments(comments)
}
handleDeleteComment(index) {
const {comments} = this.props
const newComments = [
...comments.slice(0, index),
...comments.slice(index + 1)
]
localStorage.setItem('comments', JSON.stringify(newComments))
if(this.props.onDeleteComment) {
this.props.onDeleteComment(index)
}
}
render() {
return (
< CommentList
comments = {this.props.comments}
onDeleteComment={this.handleDeleteComment.bind(this)}
/ >
)
}
}
// 评论列表从 state.comments 中获取
const mapStateToProps = state => {
return {
comments: state.comments
}
}
const mapDispatchToProps = dispatch => {
return {
// 提供给 CommentListContainer
// 当从 LocalStorage 加载评论列表以后就会通过这个方法
// 把评论列表初始化到 state 当中
initComments: (comments) => {
dispatch(initComments(comments))
} ,
// 删除评论
onDeleteComment: (commentIndex) => {
dispatch(deleteComment(commentIndex))
}
}
}
// 将 CommentListContainer connect 到 store
// 会把 comments、initComments、onDeleteComment 传给 CommentListContainer
export default connect(
mapStateToProps,
mapDispatchToProps
)(CommentListContainer)
middleware
强化 redux 的功能
原理
改写 store.dispatch
因为 reducer 是纯函数,只承担计算 State 的功能,不合适承担其他功能
View 与 State 一一对应,可以看作 State 的视觉层,也不合适承担其他功能。
Action:存放数据的对象,即消息的载体,只能被别人操作,自己不能进行任何操作。
compose
从右到左来组合多个函数。
这是函数式编程中的方法,为了方便,被放到了 Redux 里。
当需要把多个 store 增强器 依次执行的时候,需要用到它。
例子
import {createStore, applyMiddleware, compose} from 'redux'
import reducers from './reducers.js'
import thunkMiddleware from 'redux-thunk'
import createLogger from 'redux-logger'
export default () => {
const middleware = [thunkMiddleware, createLogger]
const composeEnhancers =
process.env.NODE_ENV !== 'production' &&
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
})
: compose
const enhancers = composeEnhancers(
applyMiddleware(...middleware)
)
const store = createStore(
reducers,
enhancers
)
return store
}
处理异步
redux-think + async/await
redux-think 让 dispatch 能接受 函数作为参数 (原来参数只能是对象)
利用 async/await 的调用方式处理异步
redux-promise
利用 promise 的调用方式处理异步
redux-promise-middleware
优化 redux-promise
redux-saga (generator/yield)
利用 generator/yield 的调用方式处理异步
提供大量的 api
redux-observable (RxJS)
利用 RxJS 的调用方式处理异步
提供大量的 api
redux-loop
其他中间件
redux-logger
最佳实践
看看 dva 的前身 React + Redux 最佳实践,知道 dva 是怎么来的
优秀的相关框架
参考资料
理解 React: https://www.zhihu.com/question/41312576?sort=created
Redux 入门教程(一)—— 阮一峰 : http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
许可协议: "署名-非商用-相同方式共享 4.0"
本文链接:http://ldq-first.github.io/2017/07/23/Redux-简介/