This article brings you an introduction to using RxJS to manage React application status. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
As front-end applications become more and more complex, how to manage application data has become an unavoidable problem. When you are faced with a large front-end application with complex business scenarios, frequent demand changes, and various application data that are interrelated and dependent, how will you manage the status data of the application? We believe that application data can be roughly divided into four categories:
Events: data generated in an instant. The data is destroyed immediately after being consumed and is not stored. is naturally suitable for writing asynchronous and event-based programs, so how to manage state data? Should I still use RxJS
? Is it suitable? We investigated and learned about the excellent state management solutions already available in the front-end community, and also learned from the ideas and practices shared by some experts about using
to design the data layer. Inspiration:
Redux
, Mobx
, etc. to manage state data.
The application data is not only status, but also events, asynchronous, constants, etc. If the entire application is expressed by RxJS
's sequence-based and responsive features. Abstract reusable and scalable business models more elegantly and efficiently.
. Principle Introduction
For the definition of state, it is generally believed that the state needs to meet the following three conditions:
is a set with multiple values.action
to get a new value.
There is the concept of "current value". Generally, only the current value, that is, the latest value, is exposed to the outside world. is suitable for managing state data? The answer is yes!
Observable itself is a push collection of multiple values, the first condition is met!
observable that uses the dispatch action
pattern to push data to satisfy the second condition!As we all know,
in RxJS
can be divided into two types:
: producer of pushed values (producer
) comes from inside observable
.
observer
), which is unicast.
Whenever producer
will push several predefined values to observer
in sequence.
: The producer
that pushes the value comes from observable
externally.
observer
have a one-to-many relationship, that is, multicast.
Whenever observer
will be registered in the observer list, similar to addListener
in other libraries or languages. way of working.
When the external observer
at the same time; that is, all observer
Shared the value pushed by hot observable
. The BehaviorSubject
provided by RxJS
is a special hot observable
, which exposes the interface for pushing data to the outside worldnext
function; and there is the concept of "current value", which saves the latest value sent to observer
. When a new observer subscribes, it will be immediately retrieved from BehaviorSubject
That receives the "current value".
BehaviorSubject to update the state and save the current value of the state, and the third condition is also met. Simple implementation
Please look at the following code:
import { BehaviorSubject } from 'rxjs'; // 数据推送的生产者 class StateMachine { constructor(subject, value) { this.subject = subject; this.value = value; } producer(action) { let oldValue = this.value; let newValue; switch (action.type) { case 'plus': newValue = ++oldValue; this.value = newValue; this.subject.next(newValue); break; case 'toDouble': newValue = oldValue * 2; this.value = newValue; this.subject.next(newValue); break; } } } const value = 1; // 状态的初始值 const count$ = new BehaviorSubject(value); const stateMachine = new StateMachine(count$, value); // 派遣action function dispatch(action) { stateMachine.producer(action); } count$.subscribe(val => { console.log(val); }); setTimeout(() => { dispatch({ type: "plus" }); }, 1000); setTimeout(() => { dispatch({ type: "toDouble" }); }, 2000);
The execution code console will print out three values:
Console 1 2 4
The above The code simply implements an example of simple state management:
Initial value of state: 1
State value after executing
to express the current value of the state: <ul>
<li>第一步,通过调用<code>dispatch
函数使producer
函数执行
producer
函数在内部调用了BehaviorSubject
的next
函数,推送了新数据,BehaviorSubject
的当前值更新了,也就是状态更新了。不过写起来略微繁琐,我们对其进行了封装,优化后写法见下文。
我们自定义了一个操作符state
用来创建一个能够通过dispatch action
模式推送新数据的BehaviorSubject
,我们称她为stateObservable
。
const count$ = state({ // 状态的唯一标识名称 name: "count", // 状态的默认值 defaultValue: 1, // 数据推送的生产者函数 producer(next, value, action) { switch (action.type) { case "plus": next(value + 1); break; case "toDouble": next(value * 2); break; } } });
在你想要的任意位置使用函数dispatch
派遣action
即可更新状态!
dispatch("count", { type: "plus" })
RxJS
的一大优势就在于能够统一同步和异步,使用observable
处理数据你不需要关注同步还是异步。
下面的例子我们使用操作符from
将promise
转换为observable
。
observable
作为状态的初始值(首次推送数据)const todos$ = state({ name: "todos", // `observable`推送的数据将作为状态的初始值 initial: from(getAsyncData()) //... });
producer
推送observable
const todos$ = state({ name: "todos", defaultValue: [] // 数据推送的生产者函数 producer(next, value, action) { switch (action.type) { case "getAsyncData": next( from(getAsyncData()) ); break; } } });
执行getAsyncData
之后,from(getAsyncData())
的推送数据将成为状态的最新值。
由于状态todos$
是一个observable
,所以可以很自然地使用RxJS
操作符转换得到另一个新的observable
。并且这个observable
的推送来自todos$
;也就是说只要todos$
推送新数据,它也会推送;效果类似于Vue
的计算属性。
// 未完成任务数量 const undoneCount$ = todos$.pipe( map(todos => { let _conut = 0; todos.forEach(item => { if (!item.check) ++_conut; }); return _conut; }) );
我们可能会在组件的生命周期内订阅observable
得到数据渲染视图。
class Todos extends React.Component { componentWillMount() { todos$.subscribe(data => { this.setState({ todos: data }); }); } }
我们可以再优化下,利用高阶组件封装一个装饰器函数@subscription
,顾名思义,就是为React组件订阅observable
以响应推送数据的变化;它会将observable
推送的数据转换为React组件的props
。
@subscription({ todos: todos$ }) class TodoList extends React.Component { render() { return ( <p className="todolist"> <h1 className="header">任务列表</h1> {this.props.todos.map((item, n) => { return <TodoItem item={item} key={item.desc} />; })} </p> ); } }
使用RxJS
越久,越令人受益匪浅。
observable
序列提供了较高层次的抽象,并且是观察者模式,可以尽可能地减少各组件各模块之间的耦合度,大大减轻了定位BUG和重构的负担。observable
序列来编写代码的,所以遇到复杂的业务场景,总能按照一定的顺序使用observable
描述出来,代码的可读性很强。并且当需求变动时,我可能只需要调整下observable
的顺序,或者加个操作符就行了。再也不必因为一个复杂的业务流程改动了,需要去改好几个地方的代码(而且还容易改出BUG,笑~)。所以,以上基于RxJS
的状态管理方案,对我们来说是一个必需品,因为我们项目中大量使用了RxJS
,如果状态数据也是observable
,对我们抽象可复用可扩展的业务模型是一个非常大的助力。当然了,如果你的项目中没有使用RxJS
,也许Redux
和Mobx
是更合适的选择。
这套基于RxJS
的状态管理方案,我们已经用于开发公司的商用项目,反馈还不错。所以我们决定把这套方案整理成一个js lib
,取名为:Floway
,并在github
上开源:
【相关推荐:react视频教程】
The above is the detailed content of An introduction to using RxJS to manage React application state. For more information, please follow other related articles on the PHP Chinese website!