2020年React Redux的5种可替代品

2020-11-17大约26分钟

Redux实际上是一个和视图层无关的一个库,因此Redux已成为使用React,Vue或Angular作为前端框架的大多数应用程序的流行的状态管理解决方案。Redux受欢迎的主要原因之一是其轻巧,压缩后的大小只有2KB左右。在前端,轻量意味着加载更快、执行也更快。

Redux的简单原则是将应用程序的整个状态存储在一个中央存储(Store)中。所有组件都可以访问该存储,因此无需在组件之间传递参数和属性。Redux的主要模块是它的Action,Reducer和Store。

让我们先看看Redux是如何工作的,以便更好地了解Redux及其替代品之间的区别。

图片

Action

只要组件中发生状态更改,就会触发动作创建者(action creator)。动作创建者(action creator)是一个称为动作(action )的函数,这个函数将纯粹的JS对象(Plain JS Object)发送到Store,action是商店的唯一数据来源。

Reducer

Action会把对象返回给Reducer处理。Reducer是根据对象的旧状态返回新状态的函数,根据Action的类型来做具体的处理。

Store

Store保存应用程序状态,允许对状态进行访问和更新。

Provider

Provider把store中抽取的数据绑定到组件上。

为什么我们需要Redux的替代产品?

Redux及其用法听起来很简单,但存在一些缺点:

  1. 有相当大的学习曲线。因为必须具备函数式编程知识, 学习Redux可能会变得更加困难。
  2. 增加了简单的更改的样板代码。由于redux中的流是预定义的,因此你必须这么用。在较小的应用程序中,样板代码的数量似乎更多。
  3. 即使是很小的更改在Redux中也会触发DOM重建过程。作为开发人员,我们不喜欢这样,这样很耗时,并且会对性能产生不利影响。

Redux的替代品

因为Redux的这些缺点,大家又创建了许多能够用来代替Redux的状态管理库。这些新的库,各有各的优缺点,让我们看一看有哪些好的方案,并了解它们最适合什么。

MobX

图片

MobX通过应用反应式编程的概念来同步模型和UI。它仅更新UI的必需部分,而不是完全重新加载它。MobX建立在面向对象的模型基础上,用store来统一管理应用程序所用到的属性和对这些属性操作的方法。因为添加或者更新状态几乎不需要样板代码,因此可以让开发过程更加快速。

图片

以下是MobX的主要优势:

  • 直截了当 。编写简约的、消除样板代码来抓住你的意图。尝试更新记录字段?使用JavaScript旧有的赋值方式。在异步过程中更新数据?不需要特殊工具,反应系统(reactivity system)将检测你的所有更改并将其传播到使用它们的地方。

  • 毫不费力的最佳渲染 。在运行时跟踪对数据的所有更改和使用,从而构建一个依赖树,以捕获状态和输出之间的所有关系。这保证了取决于状态的计算(例如React组件)仅在严格需要时才运行。无需使用容易出错和次优技术(如memoization和选择器)来手动优化组件。

  • 架构自由 。MobX不带偏见,可让您在任何UI框架之外管理应用程序状态。这使您的代码解耦,可移植,并且最重要的是,易于测试。

这是使用MobX的一个简单示例:

import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react"

// Model the application state.
class Timer {
    secondsPassed = 0

    constructor() {
        makeAutoObservable(this)
    }

    increase() {
        this.secondsPassed += 1
    }

    reset() {
        this.secondsPassed = 0
    }
}

const myTimer = new Timer()

// Build a "user interface" that uses the observable state.
const TimerView = observer(({ timer }) => (
    <button onClick={() => timer.reset()}>Seconds passed: {timer.secondsPassed}</button>
))

ReactDOM.render(<TimerView timer={myTimer} />, document.body)

// Update the 'Seconds passed: X' text every second.
setInterval(() => {
    myTimer.increase()
}, 1000)

基于其透明的反应式编程,MobX被广泛用作Redux的替代品。Mobx和React使用需要和Mobx-react库一起使用,因此使用这两个库需要加载的minifiy过的代码大小是46KB+12KB=58KB。

Apollo GraphQL

图片

Apollo GraphQL引入了将现代应用程序连接到云的数据图层。React可以与需要从服务器获取数据的REST API一起使用。在现代的系统中,有必要获取大量数据。但是,这并不太不可行的。GraphQL通过允许组件声明数据来弥合这种差距。强大的端到端键入功能可提高服务器与应用程序之间的性能。

该平台在集中位置管理数据。您可以简单地连接平台或微服务,并在这些系统之间连接必要的数据。GraphQL进行数据获取和数据转换。通过创建抽象层,它有助于使服务解耦。GraphQL独立于平台和语言。

图片

Context API和React Hooks

自从钩子(Hooks)创建以来,便已与上下文API(Context API)结合使用来管理状态。

为什么要使用钩子和上下文?我个人更喜欢在中小型应用程序中使用它们,因为它们使我更易于将可重用组件发布到Bit中。这个方案中主要都是用React自身带的功能,因此理论上没有多引入额外的框架代码。

PullState

图片

PullState的工作方式与Redux类似,但不提供类支持。它使用钩子进行全局状态管理,可以使用钩子创建多个store,并使用“useState”访问状态值。使用挂钩,我们确保为组件使用所需的状态。PullState依赖Immer这个库,因此总的大小是(minify过但是未zip压缩)22KB+16KB=38KB。

这是一个使用PullState更改样式属性的示例。首先,为您的主题创建一个store。

import { Store } from "pullstate";

export const UIThemeStore = new Store({
  isRedTheme: true
});

接下来,我们将读取状态并在单击按钮时切换状态

import React from "react";
import "./styles.css";
import { UIThemeStore } from "./UIStore";

export default function App() {
  const isRedTheme = UIThemeStore.useState(s => s.isRedTheme);

  return (
    <div
      style={{
        background: isRedTheme ? "red" : "yellow",
        color: isRedTheme ? "yellow" : "red"
      }}
    >
      <h1>Toggle Modes using Pull State</h1>
      <button
        onClick={() =>
          UIThemeStore.update(s => {
            s.isRedTheme = !isRedTheme;
          })
        }
      >
        Toggle Red theme
      </button>
    </div>
  );
}

RxJs

RxJS是一个反应式扩展JS库(RxJS),它使用Observables进行异步调用。它基于事件,可以为应用程序提供更好的性能和模块化,显示更好的可调试调用堆栈,并具有向后兼容性。RxJS中最常用的概念是Observable,Scheduler和Subject。

这是RxJS的自定义钩子的简单片段,其中:

  1. 使用“useEffect”钩子来订阅一个Observable
  2. 设置更改状态
  3. 清理函数功能
const setObservable = observable => {
  const [state, setState] = useState();

  useEffect(() => {
    const sub = observable.subscribe(setState);
    return () => sub.unsubscribe();
  }, [observable]);

  return state;
};

结论

我们研究了Redux的一些最常用替代方法,它们可以独立工作或可以在React应用程序中与Redux交互。MobX和Apollo GraphQL使用最广泛,并且分别以性能和连接许多不同平台的能力而著称。

许多其他人更喜欢Reactive Extension JS(RxJS)库,因为它使用Hooks代替Redux。

最终,还是那句话,没有最好的库,你选择什么,还是归结为哪个库最适合您的项目。