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的这些缺点,大家又创建了许多能够用来代替Redux的状态管理库。这些新的库,各有各的优缺点,让我们看一看有哪些好的方案,并了解它们最适合什么。
MobX通过应用反应式编程的概念来同步模型和UI。它仅更新UI的必需部分,而不是完全重新加载它。MobX建立在面向对象的模型基础上,用store来统一管理应用程序所用到的属性和对这些属性操作的方法。因为添加或者更新状态几乎不需要样板代码,因此可以让开发过程更加快速。
以下是MobX的主要优势:
这是使用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引入了将现代应用程序连接到云的数据图层。React可以与需要从服务器获取数据的REST API一起使用。在现代的系统中,有必要获取大量数据。但是,这并不太不可行的。GraphQL通过允许组件声明数据来弥合这种差距。强大的端到端键入功能可提高服务器与应用程序之间的性能。
该平台在集中位置管理数据。您可以简单地连接平台或微服务,并在这些系统之间连接必要的数据。GraphQL进行数据获取和数据转换。通过创建抽象层,它有助于使服务解耦。GraphQL独立于平台和语言。
自从钩子(Hooks)创建以来,便已与上下文API(Context API)结合使用来管理状态。
为什么要使用钩子和上下文?我个人更喜欢在中小型应用程序中使用它们,因为它们使我更易于将可重用组件发布到Bit中。这个方案中主要都是用React自身带的功能,因此理论上没有多引入额外的框架代码。
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是一个反应式扩展JS库(RxJS),它使用Observables进行异步调用。它基于事件,可以为应用程序提供更好的性能和模块化,显示更好的可调试调用堆栈,并具有向后兼容性。RxJS中最常用的概念是Observable,Scheduler和Subject。
这是RxJS的自定义钩子的简单片段,其中:
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。
最终,还是那句话,没有最好的库,你选择什么,还是归结为哪个库最适合您的项目。