本書の翻訳版である本書の著者は、彼がアプリケーションの新機能に取り組んでいる
Hikeメッセンジャーチームの一員であると述べています。 このチームの目標は、現実に変換し、ユーザーが好む可能性のあるアイデアを探ることです。 つまり、開発者は迅速に行動する必要があり、多くの場合、ユーザーの作業をできるだけ便利で楽しいものにすることを目的として、研究しているイノベーションに変更を加える必要があります。 このライブラリは開発を高速化し、異なるプラットフォームで同じコードを使用できるため、React Nativeを使用して実験を行うことを好みます。 さらに、Reduxライブラリを使用します。

Hikeの開発者が何か新しいことに取り組んでいるとき、研究中のソリューションのアーキテクチャについて議論するとき、彼らにはいくつかの質問があります。
- これは、彼らが言うように、「飛び上がらない」ことができる実験的な機会であり、放棄する必要があります。 これを考えると、アプリケーションアーキテクチャの設計に時間を費やす必要がありますか?
- 実験的なアプリケーションは、MVPであり、1〜2画面を持ち、できるだけ早く作成する必要がある最小限の実行可能な製品です。 これを考慮して、Reduxに連絡する必要がありますか?
- プロダクトマネージャーが実験的なアプリケーションのサポートインフラストラクチャを準備するのにかかる時間をどのように正当化しますか?
実際、Reduxはこれらすべての質問に対する正しい答えを見つけるのに役立ちます。 Reduxアーキテクチャは、アプリケーションの状態をReactから分離するのに役立ちます。 これにより、アプリケーションの最上位にあるグローバルリポジトリを作成し、他のすべてのコンポーネントに状態アクセスを提供できます。
責任の分離
「責任の分離」とは何ですか?
ウィキペディアはそれについて次のように述べています。「コンピューターサイエンスでは、責任の分割とは、コンピュータープログラムを機能ブロックに分割するプロセスです。 より一般的な場合、責任の分割は、問題をサブタスクを解決するための相互作用するプロセスに分割することにより、問題を解決するための単一のプロセスの単純化です。
Reduxのアーキテクチャを使用すると、次の図に示すように、アプリケーションの責任を4つのブロックに分割して、アプリケーションに責任の分離の原則を実装できます。
Reduxアーキテクチャこれらのブロックの簡単な説明を次に示します。
- ビューまたはユーザーインターフェイスコンポーネント(UIコンポーネント)は、ストアから転送されたデータに基づいて画面に情報を表示する役割を担う純粋な機能(つまり、転送されたデータを変更せず、他のプロパティを持っている機能)に似ています。 データを直接変更することはありません。 イベントが発生した場合、またはユーザーがイベントを操作した場合、アクションの作成者に頼ります。
- アクション作成者は、アクションの作成とディスパッチを担当します。
- レデューサーは、スケジュールされたアクションを受け取り、リポジトリの状態を更新します。
- データストアは、アプリケーションデータの保存を担当します。
例としてReduxのアーキテクチャを検討してください。
異なるコンポーネントが同じデータを必要とする場合はどうなりますか?
Hikeアプリには、ユーザーの友達リストを表示する画面があります。 数量に関する情報は、この画面の上部に表示されます。
Hikeアプリの友達画面ここには3つのReactコンポーネントがあります。
FriendRow
は、ユーザーの友人の名前と彼に関するその他の情報を含むコンポーネントです。FriendsHeader
「MY FRIENDS」という碑文と友人の数に関する情報を表示するコンポーネント。ContainerView
は、 FriendsHeader
コンポーネントによって表される画面タイトルと、 FriendRow
コンポーネントによって画面に表示されるユーザーの友達に関する情報を含む配列を走査することによって取得される友達のリストを組み合わせたFriendRow
コンポーネントです。
上記を説明する
friendsContainer.jsのコードは
次のとおりです。
class Container extends React.Component { constructor(props) { super(props); this.state = { friends: [] }; } componentDidMount() { FriendsService.fetchFriends().then((data) => { this.setState({ friends: data }); }); } render() { const { friends } = this.state; return ( <View style={styles.flex}> <FriendsHeader count={friends.length} text='My friends' /> {friends.map((friend) => (<FriendRow {...friend} />)) } </View> ); } }
このようなアプリケーションページを作成する絶対に明白な方法は、友人に関するデータをコンテナコンポーネントにロードし、それらをプロパティとして子コンポーネントに渡すことです。
友人に関するこのデータは、アプリケーションで使用される他のコンポーネントで必要になる可能性があるという事実について考えてみましょう。
チャット画面をハイキングアプリケーションにチャット画面があり、そこに友人のリストも含まれているとします。 同じデータが、友人のリストを含む画面とチャット画面で使用されていることがわかります。 同様の状況で何をすべきか? 次の2つのオプションがあります。
- チャットリストを表示する
ComposeChat
コンポーネントで、フレンドデータを再度ダウンロードできます。 ただし、アプリケーションはデータの複製を意味し、同期の問題を引き起こす可能性があるため、このアプローチは特に適していません。 - 友人に関するデータを最上位コンポーネント(アプリケーションのメインコンテナ)にダウンロードし、このデータを友人のリストの表示とチャットのリストの表示を担当するコンポーネントに転送できます。 さらに、これらのコンポーネントに関数を渡してフレンドデータを更新する必要があります。これは、コンポーネント間のデータ同期をサポートするために必要です。 このアプローチにより、トップレベルのコンポーネントには、直接使用しないメソッドやデータが文字通り詰め込まれます。
これらのオプションはどちらもそれほど魅力的ではありません。 次に、Reduxアーキテクチャを使用して問題を解決する方法を見てみましょう。
Reduxを使用する
ここでは、ストレージ、アクションクリエーター、レデューサー、および2つのユーザーインターフェイスコンポーネントを使用して、データを使用して作業を整理することについて説明します。
▍1。 データウェアハウス
リポジトリには、ユーザーの友人に関するアップロードされたデータが含まれます。 このデータは、必要な場合に任意のコンポーネントに送信できます。
▍2。 アクションクリエーター
この場合、アクションの作成者は、友人に関するデータの保存と更新を目的としたイベントをディスパッチするために使用されます。
friendsActions.jsのコードは
次のとおりです。
export const onFriendsFetch = (friendsData) => { return { type: 'FRIENDS_FETCHED', payload: friendsData }; };
▍3。 減速機
レデューサーは、スケジュールされたアクションを表すイベントが到着して友人情報を更新するのを待ちます。
friendsReducer.jsのコードは
次のとおりです。
const INITIAL_STATE = { friends: [], friendsFetched: false }; function(state = INITIAL_STATE, action) { switch(action.type) { case 'FRIENDS_FETCHED': return { ...state, friends: action.payload, friendsFetched: true }; } }
▍4。 友達リストコンポーネント
このコンテナコンポーネントは、友達のデータを表示し、変更時にインターフェースを更新します。 さらに、データがない場合は、リポジトリからデータをダウンロードする責任があります。
friendsContainer.jsのコードは
次のとおりです。
class Container extends React.Component { constructor(props) { super(props); } componentDidMount() { if(!this.props.friendsFetched) { FriendsService.fetchFriends().then((data) => { this.props.onFriendsFetch(data); }); } } render() { const { friends } = this.props; return ( <View style={styles.flex}> <FriendsHeader count={friends.length} text='My friends' /> {friends.map((friend) => (<FriendRow {...friend} />)) } </View> ); } } const mapStateToProps = (state) => ({ ...state.friendsReducer }); const mapActionToProps = (dispatch) => ({ onFriendsFetch: (data) => { dispatch(FriendActions.onFriendsFetch(data)); } }); export default connect(mapStateToProps, mapActionToProps)(Container);
▍5。 チャットリストコンポーネント
このコンテナコンポーネントは、ストレージからのデータも使用し、その更新に応答します。
Reduxアーキテクチャの実装について
上記のアーキテクチャを稼働状態にするのに1〜2日かかる場合がありますが、プロジェクトに変更を加える必要がある場合は、非常に簡単かつ迅速に行われます。 友人に関するデータを使用するアプリケーションに新しいコンポーネントを追加する必要がある場合、データの同期を心配したり、他のコンポーネントをやり直したりする必要なく、これを行うことができます。 コンポーネントの削除についても同じことが言えます。
テスト中
Reduxを使用する場合、各アプリケーションブロックを個別にテストできます。
たとえば、ユーザーインターフェイスの各コンポーネントは、データに依存しないことが判明しているため、ユニットテストを簡単に実行できます。 ポイントは、そのようなコンポーネントを表す関数は、同じデータに対して常に同じ表現を返すということです。 これにより、アプリケーションが予測可能になり、データの視覚化中にエラーが発生する可能性が低くなります。
各コンポーネントは、さまざまなデータを使用して包括的にテストできます。 このようなテストにより、隠れた問題が明らかになり、高品質のコードを保証できます。
データの視覚化を担当するコンポーネントだけでなく、レデューサーやアクションクリエーターも独立したテストを受けることができることに注意してください。
Reduxは素晴らしいですが、このテクノロジーを使用すると、いくつかの困難に直面しました。
Reduxを使用した問題
▍余分なテンプレートコード
Reduxアーキテクチャをアプリケーションに実装するには、あらゆる種類の奇妙な概念やエンティティに遭遇しながら、多くの時間を費やす必要があります。
これらは、いわゆるスレッド(サンク)、レデューサー(レデューサー)、アクション(アクション)、ミドルウェアレイヤー(ミドルウェア)です。これらは、関数
mapStateToProps
および
mapDispatchToProps
だけでなく、それ以外の多くの機能です。 これらすべてを学ぶには時間がかかります。正しく使用する方法を学ぶには、練習が必要です。 プロジェクトには多くのファイルがあり、たとえば、データの視覚化のためのコンポーネントの1つの小さな変更により、4つのファイルの修正が必要になる場合があります。
Red Reduxリポジトリはシングルトンです
Reduxでは、コンポーネントは複数のインスタンスを持つことができますが、データウェアハウスはシングルトンパターンを使用して構築されます。 ほとんどの場合、これは問題ではありませんが、特定の状況では、データストレージへのこのようなアプローチはいくつかの問題を引き起こす可能性があります。 たとえば、コンポーネントのインスタンスが2つあるとします。 これらのインスタンスのいずれかでデータが変更されると、それらの変更は別のインスタンスに影響します。 場合によっては、この動作は望ましくない可能性があり、各コンポーネントインスタンスがデータの独自のコピーを使用する必要がある場合があります。
まとめ
Reduxアーキテクチャを実装するのに時間と労力をかける価値があるかどうかという主な質問を思い出してください。 この質問に答えて、Reduxは「はい」と言います。 このアーキテクチャは、アプリケーションの開発と開発における時間と労力の節約に役立ちます。 Reduxを使用すると、プログラマがアプリケーションを頻繁に変更しやすくなり、テストが簡単になります。 もちろん、Reduxアーキテクチャはかなりの量のテンプレートコードを提供しますが、コードを作業に便利なモジュールに分割するのに役立ちます。 このような各モジュールは、他のモジュールとは独立してテストできるため、開発段階でエラーを特定するのに役立ち、高品質のプログラムを保証できます。
親愛なる読者! プロジェクトでReduxを使用していますか?
