- 发布于
redux
- Authors
- Name
- 田中原
redux
目录
Redux
Redux可预测的JavaScript应用程序的状态容器
帮助你写的应用行为一致,在不同的环境(client, server,native),更容易测试,提供更好的开发体验。
Start—React-Redux
安装依赖
npm install --save redux react-redux
npm install --save-dev redux-devtools
要点
- 应用程序的整个状态存储在单个存储中的对象树中。(Redux状态容器中)
- 改变状态树的唯一方法是发出一个动作
action
,一个描述发生了什么的对象。 - 要指定动作
action
如何操作了状态树,需要自己编写reducer
redux
reducer
一个纯函数用于(state, action) => state
描述了一个action
如何将state
转换为下一个state
状态的类型(形式)取决与你自己:它可以是基本类型,一个数组,一个对象,一个Immutable.js
数据结构。
重要的一点是,你不应该改变状态对象(修改state),如何state
改变了,将会返回一个新的对象。
三原则
单一来源
整个应用程序的状态存储在单个存储中的对象树中。
state
只读改变状态的唯一方法是发出一个
action
,一个描述发生了什么的对象使用纯函数进行更改
要指定如何通过操作转换状态树,可以编写纯reducer。编写
纯函数reducer
基础
Actions
Actions
Actions
是将数据从应用程序发送到store
的行为。他们是store
的唯一信息来源。您可以使用store.dispatch()将它们发送到store
。
action
是纯JavaScript对象。action
必须具有指示要执行的操作类型的type属性。类型通常应定义为字符串常量。一旦应用程序足够大,可以将它们移动到一个单独的模块。
每个action
尽量减少数据
Action Creators
Action Creators
创建actiuon
的函数,返回action
。更容易测试
传统fulx
中,dispatch
通常在action Creators
函数调用时触发。
function addTodoWithDispatch(text) {
const action = {
type: ADD_TODO,
text
}
dispatch(action)
}
在Redux
中,进行分发,需要将Action Creators
函数返回的结果传入dispatch()
中
例如dispath(actionCreators(arg))
Reducers
Reducers
操作描述了事情发生的事实,但不指定应用程序的状态如何变化。
设计state
应用的状态全部存储在单一的对象中,那么响应UI的状态如何做到最小?
state的状态应该使用ID进行存储,区分。更方便使用。
处理 Actions
reduce
接收action
和先前的state
和动作,并返回下一个状态。
Reduce中不能进行的操作
- 修改参数
- 执行次要操作,例如:API调用,路由转换
- 调用非纯函数:
Date.now()
或Math.random()
reduce
应该是一个纯函数,输入相同返回应该相同
NOTE 不要修改旧的state,
拆分Reducers
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({}, state, {
visibilityFilter: action.filter
})
case ADD_TODO:
return Object.assign({}, state, {
todos: [
...state.todos,
{
text: action.text,
completed: false
}
]
})
case TOGGLE_TODO:
return Object.assign({}, state, {
todos: state.todos.map((todo, index) => {
if(index === action.index) {
return Object.assign({}, todo, {
completed: !todo.completed
})
}
return todo
})
})
default:
return state
}
}
上面Reducer
就过于臃肿,可以拆分开让逻辑更清晰
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, {
complate: !todo.complate
})
}
return todo
})
default:
return state
}
}
function visibilityFilyer (state = SHOW_ALL, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return action.filter
default:
return state
}
}
function todoApp (state = initialState, action) {
return {
visibilityFilter: visibilityFilter(state.visibilityFilter, action),
todos: todos(state.todos, action)
}
}
将state
切片化。reduce组合是构建Redux应用程序的基本模式。
每个reduce
只管理state
的一部分。
Redux
提供combineReducers()
方法,可以拆分Reducer
Store
Store
的职责
- 管理 app state
- 通过
getstate()
访问state - 通过
dispath(action)
更新state - 注册监听器
subscrive(listener)
- 通过subscribe(listener)返回的函数处理监听器的注销。
一个app只能有一个store
Date Flow 数据流
Redux应用程序中的数据生命周期都遵循以下4个步骤
动作是描述发生了什么的简单对象,可以在任何地方调用
Store
调用传入的reduce
根
reduce
可以将多个reduce
组合成一个状态树store
将根reduce
返回的对象作为状态存储subscribe
订阅取消订阅问题??创建store:
let store = createStore(todoApp)
传入reduce
执行订阅:返回值为取消订阅函数,执行reduce后触发回调
let unsubscribe = store.subscribe(() =>
console.log(store.getState())
)
- 触发
dispatch
store.dispatch(addTodo('Learn about actions'))
接收action
异步操作
Actions
异步最重要的两个时间点:发送异步请求和接受到响应
两个时间点都需要改变应用状态,调用reducer。通常需要三种不同的操作
- An action informing the reducers that the request began通知
reducers
异步操作开始
reducers
修改状态为isFetching
,UI显示微调框
- An action informing the reducers that the request finished successfully. 通知
reducers
请求完成
reducers
可以通过将新数据合并到它们管理的状态并重置isFetching来处理此操作。 UI将隐藏微调框,并显示提取的数据。
- An action informing the reducers that the request failed. 通知
reducers
请求失败。
reducer可以通过重置isFetching来处理此操作。此外,一些reducer可能希望存储错误消息,以便UI可以显示它。