edux 基础用法
该文档是根据Redux 中文文档写出。
基础概念
Redux 提倡将数据储存于唯一的对象树内--state,state 只能通过发起 action 来修改,action 即描述发生了什么,这样避免了其他代码随意修改 state 而造成的 bug。但是 action 又不直接修改state ,而是通过 reducer 描述 action 是如何修改 state 的。并且通过一个大的 reducer 来调用多个 reducer。
Redux 有三个原则:
- 唯一的
state reducer是一个纯函数,即相同的输入有相同的输出state是只读的
Action
Action是一个对象,这个对象中必须有一个属性type,表示这个action的动作。其他的属性可以由自己任意确定- 同时需要一个函数来作为
Action 创建函数,这个函数需要返回一个action Action的触发通过store.dispatch(action)来触发
Reducer
-
Reducer必须是一个纯函数 -
Reducer通过判断action的type来决定要如何对state进行修改 -
通常将一个大的
reducer拆分成多个小的reducer,然后将多个小的reducer组合成一个大的reducer,便于管理 -
传入
reducer的state不应该被修改,因为state只读的 -
注意
reducer,应该是一个纯函数,即相同的输入,输出应该是相同的。 -
每个小的
reducer只管理一部分的state// 小 reducer const addTodo = (state, action) => { ... } // 小 reducer const filter = (state, action) => { ... } // 大 reducer const todoApp = (state = {}, action) => { return { todos: addTodo(...), filter: filter(...) } } // 这样一个大的 state 就被切分为多块便于管理 // 另一种合成大 reducer 的方法 const reducer = combineReducers({ a: addTodo(...), b: filter(...) }) -
到这里我们还无法触发
reducer,需要配合store
Store
Store有一下职责:Store 就是把它们联系到一起的对象。Store 有以下职责:- 维持应用的 state;
- 提供
getState()方法获取 state; - 提供
dispatch(action)方法更新 state; - 通过
subscribe(listener)注册监听器; - 通过
subscribe(listener)返回的函数注销监听器 - 常用的有
getstate和dispatch两个
- 通过
createStore(reducer, initialState)来创建一个store。通过将reducer传入后,我们就可以在触发action后触发reducer,进而修改state - 综上我们就已经可以写一个基本的
redux功能了
// actionTypes.ts
// 在大型应用中,我们经常将 action 的 type 提取为一个单独文件
const ADD_TODOS = 'ADD_TODOS'
const FILTER = 'FILTER'
export default {
ADD_TODOS,
FILTER
}
// actions.ts
import types from './actionTypes.ts'
// action 创建函数
export const addTodo = (text: string) => {
// 返回一个 action
return {
type: types.ADD_TODO,
todo: text
}
}
export const filter = {
...
}
// reducers.ts
import types from './actionTypes.ts'
import {combineReducers} from 'redux'
// 小 reducer
const addTodo = (state = {}, action: any) => {
switch(action.type) {
case types.ADD_TODO:
return {
..state,
action.todo
}
default: return {
...state
}
}
}
const filter = (state: any, action: any) => {
switch (action.type){
case types.FILTER:
return ...
}
}
// 合并为一个大 reducer
// 这里我们注意到,传入每个小 reducer 里的并不是整个 state, 而是受该 reducer 管理的那部分
export default todoApp = (state: any, action: any) => {
return {
todos: addTodo(state.todo, action),
filter: filter(state.todo, action)
}
}
// 也可以用另一种方法
export default todoApp = combineReducers({
todos: addTodo(state.todo, action),
filter: filter(state.todo, action)
})
// store.ts
import {createStore} from 'redux'
import {reducer} from './reducer'
// 通过 creacteStore 创建一个 store。
// 回调函数 reducer 会接受两个参数,一个是 state 一个是 action
export default store = createStore(reducer, initialState)
之后我们就可以通过 store.dispacth(action) 来修改 state 了
搭配 React
- 安装
react-redux - 使用
mapStateToProp将state的一部分绑定到容器组件的props上 - 使用
mapDispatchToProp将dispatch绑定到props上 - 完成以上两步需要
connect的协助
import {connet} from 'redux'
const mapStateToProps = (state: any) => {
return {
todos: state.todos
}
}
const mapDispatchToProps = (dispatch: any) => {
return {
addTodo: (text: string) => {
dispatch(addTodo(text))
}
}
}
connect(mapStateToProps, mapDispatchToProps)(组件)
-
之前我们需要手动监听,将
store传递给所有的容器组件。现在我们使用react-redux提供的<Provider>来让所有容器组件都能访问import {Provider} from 'react-redux' import {render} from 'react-dom' import store from 'store' render( <Provider store={store}> <App /> </Provider>, document.getElementById('app') )