大家好! 最近刚找到前端的工作,公司使用 React 作为主要的开发框架,并且使用 Redux 作为状态管理的工具,最近正在学习这一块,在这边纪录一下学习到的东西~
前一阵子也有在铁人赛写过 Redux 的介绍,这次详细的介绍一下 Redux ,以及 Redux 相关的套件。
Redux 是一个资料(状态)管理套件,他是参考 meta 公司提出的 Flux 架构实作而出的。
Flux
Flux 是一种设计方式,为了控制状态与 view 的资料流不会过于繁杂,因而设计了一套将资料与 view 分离的模式,即是 Flux 。
当有 action 触发,需要改变资料或画面时,会让 dispatcher 分派指令给 store(资料),在进而改变 view ( 画面 ),如果又触发什么指令,仍然需要经过 dispatcher 派发指令,呈现单一资料流。
这是 redux 的运作模式,与上述类似,使用者在 UI 部分进行操作,发送一个 event 给 dispatcher , dispatcher 发送一个 action 给 store ,store 是储存 reducer (资料储存)的地方,并且会依据 Action 的类别对状态进行变更。当 state 变更,UI 便会呈现相对应的变化。
Actions
在使用 Redux 时,相当重要的就是 Action 的使用。透过 Action ,才能将使用者需要执行的动作执行,并且改变状态。
Flux Standard Action
Flux Stardard Action(FSA) 是基本 Action 的格式 :
const action = { type: "ADD_TODO", payload: "this is new memo"}
其中,type 为必须的,其他(包含 payload、error、meta)都是选择性的。
payload: 可以放入任何型别,传输资料。error: 传输错误与否。id: 可以放入 id ,指出是哪个 id 要求的。Action type
要使用 action ,我们可以先定义上述的 action type:
export const ADD_TODO = 'ADD_TODO';
这样在取用 action 时,就只需要引入 action type 的档案,方便使用 action type,也方便管理 action type。
Action Creator
为了产生 Actions ,可以将 action 包装成一个 function,根据不同 type 使用不同的 Action Creator。
import {ADD_TODO} from './actionType.js';const addTodo = (text) => { return { type: ADD_TODO, payload: text }}
注意:
在专案中有时候会有 XXX_SUC、XXX_FAL 的 type,主要是为了描述诸如串接 API 时是否成功或着是失败。
Reducer
Reducer 是 state 处理的地方,他就像是 Array.reduce()
中会放入的 function,会根据指定的 action 将 state 加工成下一个 state 并回传。
import * as actions from 'actionType.js';const initState = [];const reducer = (state = initState, action)=>{ switch(action.type){ case actions.ADD_TODO: return [ ...state, action.payload ]; case actions.REMOVE_TODO: return state.filter(todo => todo.id !== action.id); default: return state; }}
要注意的是,reducer 需要是一个 pure function,也就是每次输入同一个值,可以预测输出的值会是一样的,这样不仅提升可读性,也方便维护。
要做到这件事,必须要让 function 不会修改到外面的东西。immutable (不可改动)的 primate value 没有甚么问题,但 object (包含 array) 是 mutable 的,因此若是直接修改 object 及 array 的值,将会改变原本的 object、array 。为此,我们必须回传一个新的 object。
可以使用 ES6 的展开运算子做到这样的事。
另外,也建议不要在 reducer 中做条件判断,可以尝试将逻辑判断抽离 reducer ,另外写成一个 function ,可以提高可读性。
combineReducers
由于只能有一个 Reducer,如果有複数的 reducer 的话,就需要使用 combineReducers 这个 function 来合併 reducer 。
import {combineReducer} from 'readux';const rootReducer = combineReducers({ reducer1, reducer2})
参考文章:
https://chentsulin.github.io/redux/docs/basics/Actions.html