Redux
React: state ==> DOM
Redux: Store管理全局状态 ==> 让组件通信更加容易
Redux特性:
Single Source of Truth
- 可预测性
state + action = new State
- 纯函数更新
Store
理解 Store
const store = createStore(reducer)
getState()
dispatch(action)
subscribe(listener)
理解 action
一个行为动作
{
type: 'ADD_TODO',
text: 'yym'
}
理解 reducer
// state 初始值 action 动作
function todoApp(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return Object.assign({}, state, {
todos: [
...state.todos,
{
text: action.text,
completed: false
}
]
})
default:
return false
}
}
- Store
- Actions
- Reducers
- View
理解 combineReducers
理解 bindActionCreators
DEMO
import React from 'react'
import { createStore } from 'redux'
function run() {
// Store initial state
const initialState = {
count: 0
}
// reducer
const counter = (state =initialState, action) => {
switch(action.type) {
case "PLUS_ONE":
return { count: state.count + 1 }
case "MINUS_ONE":
return { count: state.count - 1 }
case "CUSTOM_COUNT":
return {
count: state.count + action.payload.count
}
default:
break;
}
}
// Create store
const store = createStore(counter)
// Action creator
function plusOne() {
// action
return { type: "PLUS_ONE" }
}
function minusOne() {
// action
return { type: "MINUS_ONE" }
}
function customCount() {
// action
return { type: "CUSTOM_COUNT" }
}
store.subscribe(() => console.log(store.getState()))
store.dispatch(plusOne())
store.dispatch(minusOne())
store.dispatch(customCount())
}
export default () => (
<div>
<button onClick={run}>Run</button>
<p>打开控制台运行结果</p>
</div>
)
React 中使用 Redux
Component ==> Connect ==> Store
import { connect } from 'react-redux'
class SidePane extends Component {
// ...
}
function mapStateToProps() {
// ...
}
connect 工作原理: 高阶组件
异步 Action, 用于 ajax 请求
View ==> Actions ==> Dispatcher(Middlewears)[中间件] ==> 成功/失败 action ==> reducers
Redux中间件 (Middleware)
- 截获 action
- 发出 action
- 异步 action 不是特殊 action, 而是多个同步 action 的组合使用
- 中间件在 dispatcher 中截获 action 做特殊处理
如何组织 Reducer 和 Action
问题 ?
- 所有 Action 放一个文件, 会无限扩展
- Action, Reducer分开, 实现业务逻辑时需要来回切换
- 系统中有哪些 Action 不够直观
解决 :
- 单个 action 和 reducer 放在同一个文件
- 易于开发: 不用在 action 和 reducer之间来回切换
- 易于维护: 每个 action 文件都很小, 容易理解
- 易于测试: 每个业务逻辑只需对应一个测试文件
- 易于理解: 文件名就是 action 名字, 文件列表就是 action 列表
不可变数据(immutable data)
- 性能优化
- 易于调试和追踪
- 易于推测
如何操作不可变数据
- 原生写法:
{...}, Object.assign
const state = { filter: 'complete', todos: [
'Learn React'
]}
const newState = { ...state, todos: [
...state.todos,
'Learn Redux'
]}
const newState2 = Object.assign({}, state, { todos: [
...state.todos,
'Learn Redux'
]})
immutability-helper
import update from 'immutability-helper'
const state = { filter: 'complete', todos: [
'Learn React'
]}
const newState = update(state, { todos: {$push: ['Learn Redux']}})
immer
import produce from 'immer'
const newState = product(state, drafState => {
drafState.todos.push('Learn Redux')
})
网友评论