Reduxとは:デザイナーガイド
公開: 2022-03-10Reduxについて聞いたことがありますか? それは何ですか? グーグルしないでください!
- 「ファンシーなバックエンドのもの。」
- 「聞いたことはありますが、それが何であるかはわかりません。 おそらくReactフレームワークですか?」
- 「Reactアプリケーションで状態を保存および管理するためのより良い方法。」
私は40人以上のデザイナーにこの質問をしました。 上記は彼らの典型的な答えです。 彼らの多くは、ReduxがReactと連携し、その仕事が「状態管理」であることを認識しています。
しかし、この「状態管理」が実際に何を意味するのか知っていますか? Reduxの本当の力は州の管理を超えていることをご存知ですか? Reduxが必ずしもReactを機能させる必要がないことをご存知ですか? Reduxを使用するかどうかについてのチームのディスカッション(または少なくともランチチャット)に参加しますか? Reduxがどのように機能するかを理解して設計したいですか?
この記事の助けを借りて、Reduxの全体像をお見せしたいと思います。Reduxで何ができるのか、なぜそれができるのか、欠点は何か、いつ使用するのか、そしてそれがデザインとどのように関係するのかです。
私の目標は、あなたのようなデザイナーを支援することです。 これまでに1行のコードを記述したことがない場合でも、Reduxを理解することは可能であり、有益である(そして楽しい)と思います。 わかりやすい英語と落書きを期待してください。コードや抽象的な話はありません。
乗る準備はできましたか?
Reduxとは何ですか?
超高レベルでは、Reduxは開発者が生活を楽にするために使用するツールです。 多くの人が聞いたことがあるかもしれませんが、その仕事は「状態管理」です。 状態管理の意味については、後ほど説明します。 この時点で、私はあなたにこの写真を残しておきます:

なぜあなたは気にする必要がありますか?
Reduxは、ルックアンドフィールよりもアプリの内部動作に関するものです。 これは、学習曲線が急なやや複雑なツールです。 それは、デザイナーとして、私たちがそれから遠く離れるべきであることを意味しますか?
いいえ、それを受け入れるべきだと思います。 カーデザイナーは、エンジンが何のためにあるのかを理解する必要がありますよね? アプリのインターフェースをうまく設計するには、設計者は内部の事柄についても確かな知識を持っている必要があります。 それが何ができるかを学び、開発者がそれを使用する理由を理解し、その利点と影響を認識する必要があります。
「デザインは、見た目や雰囲気だけではありません。 デザインはそれがどのように機能するかです。」
- スティーブ・ジョブズ
Reduxは何ができますか?
多くの人がReduxを使用してReactアプリの状態を管理しています。 これは実際の最も一般的なユースケースであり、ReduxはReactが(まだ)うまく機能しない側面を改善します。
ただし、Reduxの真の力はそれをはるかに超えていることがすぐにわかります。 状態管理が実際に何を意味するのかを学ぶことから始めましょう。
状態管理
この「状態」の意味がわからない場合は、より一般的な用語「データ」に置き換えてみましょう。 状態は、時々変化するデータです。 状態によって、ユーザーインターフェイスに表示される内容が決まります。
状態管理とはどういう意味ですか? 一般に、アプリで管理する必要があるデータには3つの側面があります。
- データの取得と保存
- UI要素へのデータの割り当て
- データの変更
Dribbbleショットページを作成しているとしましょう。 ページに表示したいデータは何ですか? それらには、作者のプロフィール写真、名前、アニメーションGIF、ハートの数、コメントなどが含まれます。

まず、これらすべてのデータをクラウド内のサーバーからフェッチして、どこかに配置する必要があります。 次に、実際にデータを表示する必要があります。 このデータの一部を、ブラウザに実際に表示されるものを表す対応するUI要素に割り当てる必要があります。 たとえば、プロフィール写真のURLをimg
タグのsrc
属性に割り当てます。
<img src='https://url/to/profile_photo'>
最後に、データへの変更を処理する必要があります。 たとえば、ユーザーがドリブルショットに新しいコメントを追加したり、スターを追加したりした場合は、それに応じてHTMLを更新する必要があります。
状態のこれら3つの側面を調整することは、フロントエンド開発の大きな部分であり、 Reactはこのタスクに対してさまざまな程度のサポートを提供しています。 Reactの組み込み機能で十分に機能する場合があります。 ただし、アプリがより複雑になると、Reactだけでその状態を管理するのが難しくなる可能性があります。 そのため、多くの人が代わりにReduxを使い始めています。
データの取得と保存
Reactでは、UIをコンポーネントに分割します。 これらの各コンポーネントは、より小さなコンポーネントに分解できます(「Reactとは」を参照)。

UIがこのように構成されている場合、UIにデータを入力する前に、いつデータを取得し、どこに保存するのでしょうか。
各コンポーネントにシェフが住んでいると想像してみてください。 サーバーからデータを取得することは、料理を準備するために必要なすべての材料を調達するようなものです。
素朴な方法は、必要な場所と時間にデータをフェッチして保存することです。 これは、各シェフが遠くの農場から直接野菜や肉を買いに行くようなものです。

このアプローチは無駄です。 同じデータであっても、多くのコンポーネントからサーバーを何度も呼び出す必要があります。 シェフは、行き来するのに多くのガスと時間を浪費するでしょう。
Reduxを使用すると、データを1回フェッチして、「ストア」と呼ばれる中央の場所に保存します。 これで、データは任意のコンポーネントでいつでも使用できるようになります。 これは、シェフがすべての食材を購入できるスーパーストアが近くにあることと同じです。 スーパーストアは、農場から野菜や肉をまとめて持ち帰るためにトラックを送ります。 個々のシェフに自分で農場に行くように頼むよりもはるかに効率的です!
このストアは、信頼できる唯一の情報源としても機能します。 コンポーネントは、他の場所からではなく、常にストアからデータを取得します。 これにより、すべてのUIコンテンツの一貫性が保たれます。

UI要素へのデータの割り当て
Reactだけを使用すると、実際にはデータをフェッチして保存するためのより良い方法があります。 とても親切なシェフのショットウェルに、彼のすべてのシェフの友達のために買い物をするように頼むことができます。 彼はトラックを農場まで運転し、品物を持ち帰りました。 コンテナコンポーネント(たとえば、Dribbbleの例の「Shot」コンポーネント)からデータをフェッチし、それを信頼できる唯一の情報源として使用できます。

このアプローチは、すべてのコンポーネントからデータをフェッチする単純な方法よりも効率的です。 しかし、ショットウェルはどのようにして材料を他のシェフに渡すのでしょうか? HTML要素を実際にレンダリングするコンポーネントにデータを渡す方法は? データが宛先に到達するまで、外部コンポーネントからリレー内のバトンなどの内部コンポーネントにデータを渡します。
たとえば、作成者のアバターのURLは、「Shot」、「ShotDetail」、「Title」、最後に<img>
タグに渡す必要があります。 私たちのシェフがアパートに住んでいる場合、それは実際には次のようになります。

データを宛先に配信するには、データをまったく必要としない場合でも、パス上のすべてのコンポーネントを使用する必要があります。 フロアが多ければ本当に迷惑です!
スーパーストアが訪問販売を行う場合はどうなりますか? Redux 1を使用すると、次のように、他のコンポーネントにまったく影響を与えることなく、任意のデータを任意のコンポーネントにプラグインできます。
1絶対的に正確に言うと、Redux自体ではなくReactコンポーネントにデータを渡すのはreact-redux
と呼ばれる別のライブラリです。 しかし、react-reduxは配管を行うだけであり、ほとんどの場合、Reduxとreact-reduxを一緒に使用するため、これをReduxの利点の1つとして含めることは問題ないと思います。

注: Reactの最新バージョン(16.3)には、データをコンポーネントにプラグインするという点でほぼ同じ仕事をする新しい「コンテキスト」APIがあります。 したがって、これがチームがReduxを使用している唯一の理由である場合は、React16.3へのアップグレードを真剣に検討してください。 詳細については、公式ドキュメントを確認してください(警告:多くのコードが先にあります)。
データの変更
アプリのデータを更新するロジックは、かなり複雑になる場合があります。 これには、相互に依存する複数のステップが含まれる場合があります。 アプリケーションの状態を更新する前に、複数のサーバーからの応答を待つ必要がある場合があります。 さまざまな条件の下で、さまざまな時期に州内の多くの場所を更新する必要がある場合があります。
このすべてのロジックに適した構造がないと、圧倒される可能性があります。 コードを理解して維持するのは難しいでしょう。
Reduxを使用すると、分割統治が可能になります。 これは、データ更新ロジックを小さな「レデューサー」に分割する標準的な方法を提供します。 これらのレデューサーは協調して動作し、複雑なアクションを完了します。


ただし、Reactの最近の開発に注目してください。 「コンテキスト」APIと同様に、Reactの将来のバージョンには新しい「setState」APIが含まれる可能性があります。 複雑な更新ロジックをより小さな部分に分割するのが簡単になります。 この新しいAPIが利用可能になると、状態管理のこの側面を管理するためにReduxが不要になる可能性があります。
Reduxの真の力
これまでのところ、ReduxはReactの単なるバンドエイドのようです。 人々はReduxを使用して、Reactが(まだ)うまく機能しない側面を改善します。 しかし、Reactはすぐに追いついてきています! 実際、Reduxの作成者であるDan Abramovは、数年前にFacebookのReactコアチームに加わりました。 彼らは、前述のReactの改善に忙しく取り組んでいます:コンテキストAPI(16.3でリリース)、より優れたデータフェッチAPI(2018年2月にデモ)、より優れたsetStateAPIなど。
Reduxは時代遅れになりますか?
何だと思う? Reduxの本当の力はまだお見せしていません!

Reduxは、開発者にいくつかの厳格なルールに従うように強制します。これにより、Reduxに多くの力がもたらされます(うん、規律の力!):
- すべてのデータ(アプリケーションの状態)は、クリアテキストで記述する必要があります。 紙にペンですべてのデータを書き留めることができるはずです。
- すべてのアクション(データの変更)は、クリアテキストで説明する必要があります。 何かを変更する前に、何をするかを書き留めておく必要があります。 マークを付けずにデータを変更することはできません。 このプロセスは、Reduxスラングでは「アクションのディスパッチ」と呼ばれます。
- データを変更するコードは、数式のように動作する必要があります。 同じ入力が与えられた場合、同じ結果を返す必要があります。 4の二乗は、何度実行しても常に16です。
これらのルールに従ってアプリを作成すると、魔法が起こります。 それは、他の方法では実装が困難または高価な多くのクールな機能を可能にします。 下記は用例です。 2
2これらの例は、DanAbramovの投稿「YouMightNo NeedRedux」と彼の「ReactBeginnerQuestionThread」から収集しました。
元に戻す、やり直し
人気のある元に戻す/やり直し機能には、システムレベルの計画が必要です。 元に戻す/やり直すには、アプリ内のデータのすべての変更を記録して再生する必要があるため、アーキテクチャでは最初からそれを考慮に入れる必要があります。 後から考えると、たくさんのファイルを変更する必要があり、これは無数のバグのレシピです。

Reduxではすべてのアクションをクリアテキストで説明する必要があるため、元に戻す/やり直しのサポートはほぼ無料です。 Reduxで元に戻る/やり直しを実装する方法の説明は、簡単なページに収まります。
コラボレーション環境
複数のユーザーが複雑なタスクで一緒に作業するGoogleドキュメントに似たアプリを作成している場合は、Reduxの使用を検討してください。 それはおそらくあなたのために多くの重量挙げをするでしょう。

Reduxを使用すると、ネットワーク上で起こっていることを非常に簡単に送信できます。 別のユーザーが別のマシンで実行するアクションを受け取り、変更を再生して、ローカルで起こっていることとマージするのは簡単です。
楽観的なUI
楽観的なUIは、アプリのユーザーエクスペリエンスを向上させる方法です。 これにより、アプリは低速のネットワーク上でより速く応答するように見えます。 これは、ファーストパーソンシューティングゲームなど、リアルタイムの応答を必要とするアプリで人気のある戦略です。

簡単な例として、Twitterアプリでは、ツイートのハートをクリックすると、そのツイートがまだ存在するかどうかなど、サーバーにいくつかのチェックを要求する必要があります。 結果を何秒も待つ代わりに、アプリはチートを選択します! それはすべてがOKであると仮定し、すぐに満たされた心を示します。

ほとんどの場合、すべてがOKであるため、このアプローチは機能します。 問題がない場合、アプリは以前のUI更新を元に戻し、サーバーからの実際の結果を適用します。たとえば、エラーメッセージを表示します。
Reduxは、元に戻しややり直しの場合と同じ方法で楽観的なUIをサポートします。 サーバーから否定的な結果を受け取ったときに、データの変更を簡単に記録、再生、および元に戻すことができます。
永続化と状態からの起動
Reduxを使用すると、アプリで発生していることをストレージに簡単に保存できます。 後で、コンピューターが再起動した場合でも、アプリはすべてのデータをロードして、中断されたことがないかのように、まったく同じ場所から続行できます。

Reduxを使用してゲームを構築する場合、残りのコードを変更せずに、ゲームの進行状況を保存/ロードするために、さらに数行のコードが必要になります。
本当に拡張可能なシステム
Reduxでは、アプリ内のデータを更新するためのアクションを「ディスパッチ」する必要があります。 この制限により、アプリで起こっていることのほぼすべての側面にフックすることが可能になります。
すべての機能をユーザーがカスタマイズできる、非常に拡張性の高いアプリを作成できます。 たとえば、Reduxで構築されたターミナルアプリであるHyperをチェックしてください。 「hyperpower」拡張機能は、カーソルにスプリンクルを追加し、ウィンドウを揺り動かします。 この「すごい」モードはどうですか? (おそらくそれほど有用ではありませんが、ユーザーを感動させるには十分です)

タイムトラベルデバッグ
アプリをデバッグするときにタイムトラベルできるのはどうですか? アプリを実行し、数回巻き戻しまたは早送りしてバグが発生した正確な場所を見つけ、バグを修正して再生し、確認します。
Reduxは、開発者のこの夢を実現させます。 Redux DevToolsを使用すると、スライダーをドラッグすることで、実行中のアプリの進行状況をYouTubeビデオとして操作できます。
それはどのように機能しますか? Reduxが適用する3つの厳格なルールを覚えていますか? それが魔法の秘訣です。

自動バグレポート
これを想像してみてください。ユーザーがアプリに何か問題を見つけ、バグを報告したいと考えています。 彼女は自分がしたことを丹念に思い出し、説明します。 次に、開発者は手順を手動で実行して、バグが再度発生するかどうかを確認します。 バグレポートはあいまいまたは不正確である可能性があります。 開発者はバグがどこにあるかを見つけるのに苦労しています。
さて、これはどうですか。 ユーザーは「バグの報告」ボタンをクリックします。 システムは、彼女が行ったことを開発者に自動的に送信します。 開発者は「バグの再生」ボタンをクリックして、そのバグが正確にどのように発生するかを監視します。 バグはその場で潰され、みんな幸せです!
これは、Redux BugReporterを使用した場合に発生することとまったく同じです。 それはどのように機能しますか? Reduxの制限は不思議に思います。

Reduxの欠点
Reduxが適用する3つの主要なルールは、両刃の剣です。 それらは強力な機能を有効にしますが、同時に避けられない欠点を引き起こします。
急な学習曲線
Reduxの学習曲線は比較的急です。 そのパターンを理解し、覚えて、慣れるには時間がかかります。 ReduxとReactの両方が初めての場合は、同時に学ぶことはお勧めしません。
「ボイラープレート」コード
多くの場合、Reduxを使用することはより多くのコードを書くことを意味します。 単純な機能を動作させるには、多くの場合、複数のファイルに触れる必要があります。 人々は、Reduxで書かなければならない「ボイラープレート」コードについて不満を持っています。
私は知っています、これは矛盾しているように聞こえます。 Reduxが最小限のコードで機能を実装することを可能にすると言っていませんか? これは、食器洗い機を使用するのと少し似ています。 まず、料理を注意深く並べるのに時間を費やす必要があります。 それまでは、食器洗い機の利点がわかります。実際に食器を掃除したり、食器を消毒したりする時間を節約できます。準備時間に見合う価値があるかどうかを判断する必要があります。
パフォーマンスペナルティ
Reduxは、適用される制限により、パフォーマンスにも影響を与える可能性があります。 データが変更されるたびに少しオーバーヘッドが追加されます。 ほとんどの場合、それは大したことではなく、減速は目立ちません。 それでも、ストアに大量のデータがあり、データが頻繁に変更される場合(たとえば、ユーザーがモバイルデバイスですばやく入力している場合)、結果としてUIが遅くなる可能性があります。
ボーナス:ReduxはReactだけのものではありません
よくある誤解は、ReduxはReact専用であるというものです。 ReduxはReactなしでは何もできないようです。 実際、前述したように、Reduxはいくつかの重要な方法でReactを補完します。 これは最も一般的なユースケースです。
ただし、実際には、Reduxは、Angular、Ember.js、jQuery、さらにはバニラJavaScriptなどのフロントエンドフレームワークで動作します。 それをグーグルしてみてください、あなたはこれ、これ、これ、あるいはこれさえ見つけるでしょう。 Reduxの一般的な考え方はどこにでも当てはまります!
Reduxを賢く使用する限り、Reactアプリだけでなく、多くの状況でその利点を得ることができます。

結論
他のツールと同様に、Reduxにはトレードオフがあります。 強力な機能を有効にしますが、避けられない欠点もあります。 開発チームの仕事は、トレードオフがそれだけの価値があるかどうかを評価し、意識的な決定を下すことです。
デザイナーとして、Reduxの長所と短所を理解すれば、デザインの観点からこの意思決定に貢献することができます。 たとえば、潜在的なパフォーマンスへの影響を軽減するようにUIを設計できますか? おそらく、大量の確認ダイアログを削除するために、元に戻す/やり直し機能を含めることを提唱することができますか? 比較的低コストでユーザーエクスペリエンスを向上させるので、おそらく楽観的なUIを提案できますか?
テクノロジーの利点と制限を理解し、それに応じて設計します。 それが、スティーブ・ジョブズが「デザインはそれがどのように機能するか」という意味だと思います。