Open rccoder opened 7 years ago
随着场景的复杂化,在异步结果得到之后再进行 dispatch 变得越来越不可取与不可维护。Redux 自身并没打算解决这个问题,但由于提供了 middleware,可以在这层上做文章。
比较熟知的 Redux 异步 middleware 有 redux-thunk, redux-promise, redux-saga 等。
关于这些 middlware 如何使用,可以参考我近期校对过的文章 Redux 异步四兄弟,如果怀疑文章翻译的准确度,可以直接看原文 Redux 4 ways。
Redux 自身没有要求 action 应该是什么格式,但按照一些实践,我们知道 action 一般包含 type 和 payload。
那如何更好的去写出标准化的 action 呢?可以看 redux-actions。
如果不想仔细看 redux-actions 相关介绍,可以简单看一下我下面的介绍:
如果在多人开发中,不对 action 的设计做一定的规范,就可能会出现多种不同形式的 action,比如:
type:...|text:... { type: ..., data: ..., } { actionType: ..., data: ..., } { type: ..., payload: ..., }
那如何去设计一个大家可以都接受的 action 呢,在action 进化的历程中,Flux Standard Action 的设计受到广为推崇。
它约定一个 action 必须是一个对象,并且至少包含一个 key 为 type 的属性表示 action 类型。除此之外,还可以有 payload 属性表示 action 携带的数据,error 属性表示 action 是否是 “错误的”,meta 属性表示其他一些信息,当然,这只是可选的。
redux-actions 封装了一个 createAction 的函数,用它我们就能写出更加简约的 action creator,并且符合 Flux Standard Action 的标准。
createAction
以外我们写 action creator 的时候是这样:
import * as types from '../constant'; export function fetchingLogin() { return { type: types.FETCHING_LOGIN_SUCCESS, } } export function fetchingLoginSuccess(payload) { return { type: types.FETCHING_LOGIN_SUCCESS, payload, } } export function fetchingLoginFailure(payload) { return { type: types.FETCHING_LOGIN_FAILURE, payload, error: true, } }
利用 redux-actions,我们只需要这样做:
import { createAction } from "redux-actions"; import * as types from '../constant'; export const fetchingLogin = createAction(types.FETCHING_LOGIN); export const fetchingLoginSuccess = createAction(types.FETCHING_LOGIN_SUCCESS, data => data); export const fetchingLoginFailure = createAction(types.FETCHING_LOGIN_FAILURE, data => data);
这样就能创建出一个非常标准化的 action 了。
同样,我们在 reducer 中依旧可以:
import * as actions from '../action'; const initState = { status: true, } export default function isLoginReducer(state = initState, action) { switch(action.type) { case actions.CHANGE_IS_LOGIN: { return { ...state, status: action.payload, } } default: { return state; } } }
当然,redux-actions 提供了更简洁的 API handleActions 可以写出更加简约的 renducer:
handleActions
import { handleActions } from 'redux-actions'; import * as actions from '../action'; const initState = { status: true, } const isLoginReducer = handleActions({ [actions.changeIsLogin]: (state, action) => ({ ...state, status: action.payload }), }, initState); export default isLoginReducer;
这样,教会和你合作的同学使用 redux-actions,就能写出风格一致的 action。
再也不会盯着乱七八糟的 action 喊出 WTF!
业界关于 redux 的实践风格已经是保持基本一致了,也就是说按照上面 Redux 4 ways 创建出了风格基本可以解决大部分的问题。
值得注意是关于 React 组件方向最好保持纯 React 组件,保持和 Redux 之间不存在耦合。和 Redux 相关的 dispatch 可以放在 container 组件中,通过在 connect 中 mapDispatchToProps 传给 container,然后调用相应的函数即可:
import { changeIsLogin } from '../../action'; const mapDispatchToProps = (dispatch, ownProps) => { return { changeIsLogin: (status) => { dispatch(changeIsLogin(status)); } } } this.props.changeIsLogin(!this.props.isLogin.status)
Redux 异步
随着场景的复杂化,在异步结果得到之后再进行 dispatch 变得越来越不可取与不可维护。Redux 自身并没打算解决这个问题,但由于提供了 middleware,可以在这层上做文章。
比较熟知的 Redux 异步 middleware 有 redux-thunk, redux-promise, redux-saga 等。
关于这些 middlware 如何使用,可以参考我近期校对过的文章 Redux 异步四兄弟,如果怀疑文章翻译的准确度,可以直接看原文 Redux 4 ways。
标准化的 action
Redux 自身没有要求 action 应该是什么格式,但按照一些实践,我们知道 action 一般包含 type 和 payload。
那如何更好的去写出标准化的 action 呢?可以看 redux-actions。
如果不想仔细看 redux-actions 相关介绍,可以简单看一下我下面的介绍:
团队开发中的标准化 action
如果在多人开发中,不对 action 的设计做一定的规范,就可能会出现多种不同形式的 action,比如:
那如何去设计一个大家可以都接受的 action 呢,在action 进化的历程中,Flux Standard Action 的设计受到广为推崇。
它约定一个 action 必须是一个对象,并且至少包含一个 key 为 type 的属性表示 action 类型。除此之外,还可以有 payload 属性表示 action 携带的数据,error 属性表示 action 是否是 “错误的”,meta 属性表示其他一些信息,当然,这只是可选的。
redux-actions 封装了一个
createAction
的函数,用它我们就能写出更加简约的 action creator,并且符合 Flux Standard Action 的标准。以外我们写 action creator 的时候是这样:
利用 redux-actions,我们只需要这样做:
这样就能创建出一个非常标准化的 action 了。
同样,我们在 reducer 中依旧可以:
当然,redux-actions 提供了更简洁的 API
handleActions
可以写出更加简约的 renducer:这样,教会和你合作的同学使用 redux-actions,就能写出风格一致的 action。
再也不会盯着乱七八糟的 action 喊出 WTF!
听说这是最佳实践
业界关于 redux 的实践风格已经是保持基本一致了,也就是说按照上面 Redux 4 ways 创建出了风格基本可以解决大部分的问题。
值得注意是关于 React 组件方向最好保持纯 React 组件,保持和 Redux 之间不存在耦合。和 Redux 相关的 dispatch 可以放在 container 组件中,通过在 connect 中 mapDispatchToProps 传给 container,然后调用相应的函数即可:
系列文章