Rematch: Redux 的从新设想

岂非如今状况治理不是一个可以处置惩罚的题目吗?直观地说,开辟人员好像晓得一个隐蔽的现实:状况治理的运用好像比须要的更难题。在本文中,我们将讨论一些你可以一直在问本身的题目:

  • 你是不是须要一个用于状况治理的库?
  • Redux 的受迎接水平是不是值得我们去运用? 为何或许为何不值得?
  • 我们可否制订更好状况治理处置惩罚方案吗?假如能,要怎么做?

想浏览更多优良文章请猛戳GitHub博客,一年百来篇优良文章等着你!

状况治理须要一个库吗

作为前端开辟人员,不仅仅是规划,开辟的真正艺术之一是晓得怎样治理存储状况。简而言之:状况治理是庞杂的,但又并不是那末庞杂。

让我们看看运用React等基于组件的视图框架/库时的选项:

《Rematch: Redux 的从新设想》

1. Component State (组件状况)

存在于单个组件内部的状况。在React中,经由历程setState要领更新state

2. Relative State (关联状况)

从父级通报给子级的状况。在React中,将 props 作为属性通报给子组件。

3. Provided State (供应状况)

状况保存在根 provider (供应者) 组件中,并由 consumer (消费者) 在组件树的某个处所接见,而不斟酌组件之间的层级关联。在 React 中,经由历程 context API 可以完成。

大多数的状况都是存在于视图中的,因为它是用来反应用户界面的。那末,关于反应底层数据和逻辑的别的状况,又属于谁呢?

将一切内容都放在视图中可以会致使关注点的星散:它将与javascript视图库联络在一起,使代码更难测试,而且可以最大的贫苦是:必需不断地思索和调解存储状况的位置。

状况治理因为设想变动而变得庞杂,而且一般很难推断哪些组件须要哪些状况。最直接的挑选是从根组件供应一切状况,假如真要这么做的话,那末选用下一种体式格局会更好。

4. External State (外部状况)

状况可以移出视图库。然后,库可以运用供应者/消费者形式衔接以坚持同步。

或许最盛行的状况治理库是Redux。在过去的两年里,它变得愈来愈受迎接。那末为何这么喜好一个简朴的库呢?

Redux 更具机能?答案是不是定的。现实上,为了每一个必需处置惩罚的新行动(action),都邑轻微慢一些。

Redux是不是更简朴?固然不是。

简朴应当是纯javascript:比方 TJ Holowaychuk 在twitter上说

《Rematch: Redux 的从新设想》

那末为何不是每一个人都运用 global.state={}?

为何运用 Redux

在表层之下,Redux 与 TJ 的根对象{}完全相同——只是包装在了一系列实用东西的管道(pipeline)中。

《Rematch: Redux 的从新设想》

在 Redux 中,不能直接修正状况。只要一种要领:派发(Dispatch)一个行动(Action)到管道中,管道会自动依据行动去更新状况。

沿着管道有两组侦听器:中间件(middleware)定阅(subscriptions)。 中间件是可以侦听传入的行动的函数,支撑诸如“logger”,“devtools”或“syncWithServer”侦听器之类的东西。 定阅是用于播送这些状况变动的函数。

末了,合成器(Reducer)函数担任把状况变动拆分红更小、更模块化、更轻易治理的代码块。

和运用一个全局对象比拟,Redux 确切简化了开辟历程。

将 Redux 视为一个带有更新前/更新后钩子的全局对象,以及可以以简朴的体式格局合成新状况。

Redux 是不是是太庞杂了?

是的。有几个不可否认的迹象表明 API 须要革新,这些可以用下面的方程来总结

《Rematch: Redux 的从新设想》

time_saved来示意你开辟本身的处置惩罚方案所消费的时候,time_invested相当于浏览文档,进修教程和研讨不熟悉的观点所消费的时候。

Redux 是一个具有峻峭进修曲线的小型库。虽然有不少开辟者可以战胜深切进修函数式编程的难题并从 Redux 获益很多,然则也有很多开辟者望而生畏,情愿从新运用 jQuery。

运用jQuery你不须要明白“monad”是什么,你也不须要为了运用Redux去明白函数组合。

运用 jQuery 你不须要明白“comonad”是什么,你也不须要为了运用 Redux 去明白函数组合。

任何框架或许库的目标都应该是把庞杂的事物笼统得越发简朴。

从新设想Redux

我以为Redux值得重写,至少有以下 6 个方面可以革新得更友爱。

1.初始化

让我们来看看一个基础的 Redux 初始化历程,以下图左侧所示:

《Rematch: Redux 的从新设想》

很多开辟人员在第一步后就在这里停息,茫然地盯着深渊。 什么是 thunkcompose?一个函数能做到这些吗?

假如 Redux 是基于设置而不是函数组合的话,那末像右侧那样的初始化历程显著看起来越发合理。

2. 简化 reducers

Redux 中的 reducers 可以经由历程一个转换,让我们阔别已习气但不必要且冗杂的 switch 语句。

《Rematch: Redux 的从新设想》

假定reduceraction范例婚配,那末我们可以对参数举行反转,如许每一个reducer都是一个接收stateaction的纯函数。 或许更简朴,我们可以规范化action并仅传入state和有用负载(payload)。

3.运用 Async/Await 替代 Thunks

thunk 一般用于在 Redux 中建立异步 action。 在很多方面,thunk 的工作体式格局看起来更像是一个智慧的黑客,而不是官方引荐的处置惩罚方案。 我们一步一步来看:

  1. 你派发一个action(dispatch an action),它现实上是一个函数而不是预期的对象。
  2. thunk 中间件搜检每一个行动,看看它是不是是一个函数。
  3. 假如是,中间件挪用该函数,并传入一些 store 的要领:dispatchgetState

怎么会如许?一个简朴的 action 究竟是作为一个动态范例的对象、一个函数,照样一个 Promise?这岂非不是一种低劣的实践吗?

《Rematch: Redux 的从新设想》

如上图右侧所示,岂非我们就不能只运用 async/await ?

4. 两种 action

细致想一想,其实有两种 action

1.reducer action: 触发 reducer 并转变状况。

2.effect action:触发异步 action,这可以会挪用reducer操纵,但异步函数不会直接变动任何状况。

将这两种范例的 action 辨别开来,将比上面的thunk用法更有协助,也更轻易明白。

5. 不再有 action 范例(action.type)变量

为何我们的规范实践要把 action creator 和 reducer 辨别开来呢?可否只用个中一个呢?转变个中一个又是不是会影响到另一个?

action creator 和 reducer 是统一枚硬币的两面。

const ACTION_ONE = ‘ACTION_ONE’是星散 action creators 和 reducers 的一个冗余产品。应将二者视为一体,而且不再须要文件导出范例的字符串。

6.reducers 即 action creators

根据运用体式格局,把 Redux 中所触及的观点举行兼并分组,那末我们可以得出下面这个更简朴的形式。

《Rematch: Redux 的从新设想》

可以从 reducer 中自动肯定 action creator。 毕竟,在这类情况下,reducer 可以成为action creator

运用一个基础的定名商定,下面是可展望的:

  1. 假如 reducer 定名为 increment,那末 type 就是 increment。更好的做法是加上定名空间 “count/increment”
  2. 每一个 action 都经由历程 payload 键来通报数据。

《Rematch: Redux 的从新设想》

如今,从 count.increment 中,我们可以以一个 reducer 天生 action creator。

好消息:我们可以有一个更好的 Redux

以上这些痛点就是我们建立 Rematch 的缘由。

《Rematch: Redux 的从新设想》

Rematch 对 Redux 举行了封装,供应更简朴的 API,但又不失任何可设置性的特性

《Rematch: Redux 的从新设想》

请拜见下面的一个完全的 Rematch 示例:

《Rematch: Redux 的从新设想》

在过去的几个月里,我一直在现实营业中运用 Rematch。作为证实,我会说:状况治理从未变得云云简朴、高效。

Redux 与 Rematch 的对照

Redux 是一个精彩的状况治理东西,有键全的中间件生态与精彩的开辟东西。

Rematch 在 Redux 的基础上构建并减少了榜样代码和执行了一些最好实践。

说得清楚点,Rematch 移除了 Redux 所须要的这些东西:

  • 声明 action 范例
  • action 建立函数
  • thunks
  • store 设置
  • mapDispatchToProps
  • sagas

让 Redux 与Rematch 作对照有助于让明白越发清楚。

Rematch

1.model

import { init } from '@rematch/core'

const count = {
  state: 0,
  reducers: {
    upBy: (state, payload) => state + payload
  }
}

init({
  model: { count }
})

2.View

import { connect } from 'react-redux'

// Component

const mapStateToProps = (state) => ({
  count: state.count
})

const mapDispatchToProps = (dispatch) => ({
  countUpBy: dispatch.count.upBy
})

connect(mapStateToProps, mapDispatchToProps)(Component)

Redux (最好实践)

1.store

import { createStore, combineReducers } from 'redux'
// devtools, reducers, middleware, etc.
export default createStore(reducers, initialState, enhancers)

2.Action Type

export const COUNT_UP_BY = 'COUNT_UP_BY'

3.Action Creator

import { COUNT_UP_BY } from '../types/counter'

export const countUpBy = (value) => ({
  type: COUNT_UP_BY,
  payload: value,
})

4.Reducer

import { COUNT_UP_BY } from '../types/counter'

const initialState = 0

export default (state = initialState, action) => {
  switch (action.type) {
    case COUNT_UP_BY:
      return state + action.payload
    default: return state
  }
}

5.view

import { countUpBy } from '../actions/count'
import { connect } from 'react-redux'

// Component

const mapStateToProps = (state) => ({
  count: state.count,
})

connect(mapStateToProps, { countUpBy })(Component)

Rudex 与 Rematch 的分数板

《Rematch: Redux 的从新设想》

Redux 并没有被扬弃,而且也不该该被扬弃。

只是,我们应该以更低的进修本钱,更少的榜样代码和更少的认知本钱,来拥抱 Redux 背地的简朴哲学。

你的点赞是我延续分享好东西的动力,迎接点赞!

迎接到场前端大家庭,内里会常常分享一些手艺资本。

《Rematch: Redux 的从新设想》

    原文作者:前端小智
    原文地址: https://segmentfault.com/a/1190000019056045
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞