RxJSを使用してReactアプリケーションの状態を管理する実践的な共有
8506 ワード
フロントエンドアプリケーションの複雑さが高まるにつれて、アプリケーションのデータをどのように管理するかは避けられない問題である.あなたが直面しているのは
ビジネスシーンが複雑で、需要の変動が頻繁で、さまざまなアプリケーションデータが相互に関連して依存する大規模なフロントエンドアプリケーションでは、アプリケーションのステータスデータをどのように管理しますか?
アプリケーションのデータは大きく4つに分類できると考えられています.事件:瞬時に発生したデータは、データが消費された直後に破棄され、格納されない. 非同期:非同期で取得したデータ;イベントに似ており、瞬時データであり、格納されません. ステータス:時間空間が変化するデータは、常に現在の値/最新の値を格納します. 定数:不変のデータを固定します.
フロントエンドコミュニティの既存の優れた状態管理ソリューションを調査し、学習し、は、 アプリケーションのデータは、ステータスのみでなく、イベント、非同期、定数などもあります.アプリケーション全体が
以上の2つの理由から、
ステータスの定義では、通常、ステータスは次の3つの条件を満たす必要があります.は、複数の値を有する集合である. は、 には「現在値」という概念があり、一般的には現在値、すなわち最新値のみが露出される.
では、
まず、
次に、
周知のように、 は、いくつかの値をプッシュし、どのような値をプッシュするかを は、
では、いくつかの値がプッシュされ、どのような値がプッシュされるか、作成時にプッシュされるタイミングは不明です. は、 外部の
これは、
次のコードを参照してください.
コードコンソールを実行すると、次の3つの値が印刷されます.
上記のコードは、単純な管理状態の例を簡単に実現しています.状態の初期値:1 実行 実行 実装方法は、の第1のステップは、 を実行させる.第2部,
しかし、書くのは少し煩雑で、私たちはそれをパッケージして、最適化した後の書き方は以下の通りです.
オペレータ
任意の場所で関数
次の例では、オペレータ
ステータス
コンポーネントのライフサイクル内で
さらに最適化することができ、高次コンポーネントを用いて装飾関数
は、 は
したがって、以上の
この githubソース:https://github.com/shayeLee/floway 文書の使用:https://shayelee.github.io/floway 複雑な単一ページアプリケーションのデータ層設計 DaoCloud RxJSベースのフロントエンドデータ層実践
ビジネスシーンが複雑で、需要の変動が頻繁で、さまざまなアプリケーションデータが相互に関連して依存する大規模なフロントエンドアプリケーションでは、アプリケーションのステータスデータをどのように管理しますか?
アプリケーションのデータは大きく4つに分類できると考えられています.
RxJS
は生まれながらにして非同期とイベントベースのプログラムを書くのに適しているが、状態データは何で管理されているのだろうか.それともRxJS
を使いますか?合いますか?フロントエンドコミュニティの既存の優れた状態管理ソリューションを調査し、学習し、
RxJS
でデータ層を設計する構想と実践から啓発されました.RxJS
を使用して、Redux
、Mobx
などの状態データを管理する機能を完全に実現することができる.observable
によって表現される場合、RxJS
によってシーケンスベースで応答可能な特性を利用して、様々なタイプのデータをストリームのように自由につなぎ合わせ、組み合わせることができ、多重化可能で拡張可能なビジネスモデルをより優雅かつ効率的に抽象化することができる.以上の2つの理由から、
RxJS
に基づいて管理アプリケーションの状態を設計するソリューションを最終的に決定した.原理の紹介
ステータスの定義では、通常、ステータスは次の3つの条件を満たす必要があります.
event
またはaction
によって値を変換し、新しい値を得ることができる.では、
RxJS
はステータスデータの管理に適していますか?答えは肯定的だ!まず、
Observable
自体が複数の値のプッシュ集合なので、1つ目の条件は満たされています!次に、
dispatch action
モードを用いてデータをプッシュするobservable
を実現して、第2の条件を満たすことができる.周知のように、
RxJS
のobservable
は、2つのタイプに分けることができる.cold observable
:値をプッシュする生産者(producer
)は、observable
の内部から来ている.observable
が作成されたときに定義し、変更できません.producer
は、観察者(observer
)と一対一の関係、すなわち、ユニキャストである.observer
が購読するたびに、producer
が予め定義されたいくつかの値をobserver
に順次プッシュする.hot observable
:プッシュ値のproducer
はobservable
の外部から来ている.producer
とobserver
は、一対多の関係、すなわちマルチキャストである.observer
が購読されるたびに、他のライブラリまたは言語のobserver
と同様に、addListener
を観察者リストに登録する.producer
がトリガまたは実行されると、値はすべてのobserver
に同時にプッシュされる.すなわち、observer
のすべての値は、hot observable
によってプッシュされた値を共有する.RxJS
が提供するBehaviorSubject
は、プッシュデータのインタフェースhot observable
関数を外部に露出する特殊なnext
である.また、observer
に送信された最新値を保存する「現在値」という概念があり、新しいオブザーバーが購読すると、直ちにBehaviorSubject
から「現在値」が受信されます.これは、
BehaviorSubject
を用いて状態を更新し、保存する現在の値が実行可能であり、第3の条件も満たされていることを示している.単純な実装
次のコードを参照してください.
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);
コードコンソールを実行すると、次の3つの値が印刷されます.
Console
1
2
4
上記のコードは、単純な管理状態の例を簡単に実現しています.
plus
以降の状態値:2 toDouble
以降の状態値:4 BehaviorSubject
を使用して状態の現在の値を表現することです.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$
は1つの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;
})
);
Reactビューレンダリング
コンポーネントのライフサイクル内で
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 (
タスク・リスト
{this.props.todos.map((item, n) => {
return ;
})}
);
}
}
まとめ
RxJS
を長く使うほど、利益が得られます.observable
シーケンスに基づいてより高いレベルの抽象化を提供し、観察者モードであるため、各コンポーネントの各モジュール間の結合度を可能な限り低減することができ、位置決めBUGと再構成の負担を大幅に軽減することができる.observable
シーケンスに基づいてコードを記述するため、複雑なビジネスシーンに遭遇し、observable
を一定の順序で使用して記述することができ、コードの可読性が強い.そして、需要が変動した場合、observable
の順序を調整するか、オペレータを追加すればいいかもしれません.複雑な業務プロセスで変更する必要はありません.いくつかの場所のコードを変更する必要があります(しかもBUGを変更しやすく、笑~).したがって、以上の
RxJS
に基づくステータス管理スキームは、私たちのプロジェクトでRxJS
が大量に使用されているため、ステータスデータもobservable
であれば、抽象的な多重化可能な拡張性のあるビジネスモデルに非常に大きな助けになります.もちろん、あなたのプロジェクトでRxJS
を使用していない場合は、Redux
とMobx
がより適切な選択かもしれません.この
RxJS
に基づく状態管理案は、開発会社のビジネスプロジェクトに使用されており、フィードバックは悪くありません.そこで私たちはこの案をjs lib
に整理し、Floway
と名付け、github
でオープンソースを開くことにしました.star
を歓迎して、更にみんなが共同でRxJS
の使用の心得を交流して分かち合うことを歓迎します!参考記事: