blog

React Advancedへの道」の余波

コンポーネントがDOMにマウントされた後、コンポーネントのpropsまたは状態がコンポーネントを更新させることができます。コンポーネントの更新フェーズにおいて、出発のライフサイクルは次のようになります...

May 11, 2020 · 6 min. read
シェア

ReactMVCまたはMVVM

ReactはMVCのViewレイヤーに属するだけで、データ処理はReduxやMboxを使う必要があります。

React4つの機能

  • 宣言的なビュー層
  • データ駆動型ビュー
  • 仮想DOM
  • 効率的なDOM操作

Babel ES6ES5への切り替え

Babelはwebpackと連携し、コンパイル時にES6コードをAST構文ツリーに変換し、ブラウザで実行する際にはES5に変換するjavascriptコンパイラです。

JSX構文は必須ではなく、単なる構文糖です。

JSX構文は、React.createElementの構文糖に過ぎません。

Class

コンポーネントのライフサイクル

実装フェーズ

ライフサイクルのこのフェーズでは、コンポーネントが作成され、初期化が実行され、domにマウントされ、コンポーネントの最初のレンダリングが完了します:
  • constructor
  • componentWillMount
  • render
  • componentDidMount

更新フェーズ

コンポーネントがDOMにマウントされた後、コンポーネントのpropsまたは状態がコンポーネントの更新を引き起こす可能性があります。出発ライフサイクルのコンポーネント更新フェーズには
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

アンインストールフェーズ

  • componentWillUnmount

コンポーネントの状態

変数を状態として使用するかどうかを決定する方法

  • この変数は、propsを介して親コンポーネントから取得されたものですか?もしそうなら、それはステートではありません。
  • この変数は、コンポーネントのライフサイクルを通じて一定ですか?もしそうなら、それはステートではありません。
  • この変数は他の状態やプロパティから計算可能ですか?もしそうなら、それはステートではありません。
  • この変数はコンポーネントのレンダリングメソッドで使用されていますか?もしそうでなければ、それはステートではありません。この場合、この変数はコンポーネントの通常のプロパティとして定義する方が適切です。

state 状態の更新は非同期です。

setStateは複合イベントやフック関数では "非同期 "ですが、ネイティブイベントやsetTimeoutでは "同期 "です。

setState

setStateを呼び出すとき、コンポーネントの状態はすぐには変更されません。setStateは変更される状態をキューに入れるだけで、Reactは実際の実行のタイミングを最適化し、パフォーマンス上の理由から、複数のsetStateによる状態の変更を1つの状態の変更にまとめることがあります。そのため、現在の状態に依存せず、次の状態を計算してください。

stateイミュータブル・オブジェクト

  • ステートの型は不変で、直接割り当てることができます。
  • push、pop、shift、unshift、spliceなどを使って配列型の状態を変更しないでください。また、ES6 [....xxxxxx]を使用して新しい配列を作成します。
  • 1.ES6のObject.assignを使用 2.オブジェクト拡張構文{.....obj, x:1}

要約すると、新しいステートオブジェクトを作成する際のポイントは、元のオブジェクトを直接変更するようなメソッドの使用を避け、代わりに新しいオブジェクトを返すことができるメソッドを使用することです。

コンポーネント・コミュニケーション

  1. propsを介して親から子へ
  2. 子はコールバック関数を通じて父にパス
  3. ブラザーズ・コミュニケーションズ ステータスで昇格
  4. マルチレベル・ヴィア・コンテキスト・コンテキスト

ref

機能コンポーネントのインスタンスオブジェクトを取得することはできませんが、propsを介して機能コンポーネント内のdom要素を取得することは可能です。

仮想DOM

仮想DOMと実際のDOMは互いに対応しようとしています。 仮想DOMは構造化されたテキストを抽象的に表現したもので、javascriptのオブジェクトです。

<div className="foo">
 <h1>Hello React</h1>
</div>
これはJavaScriptのオブジェクトで次のように表現できる:
{
 type: 'div',
 props: {
 className: 'foo',
 children: {
 type: 'h1',
 props:{
 children: 'Hello React'
 }
 }
 }
}

diff

Diffアルゴリズムでは、新しい仮想DOMと古い仮想DOMを比較します。

  1. ルートノードが異なるタイプの場合の全体的な分解と再構築
  2. ルートノードが同じDOM要素タイプの場合、変更された属性のみが更新されます。
  3. ルートノードが同じコンポーネントの場合、1.2のルールに従って再帰的な子ノードが再帰され、再帰が完了すると、最終的な差分が計算され、実際のDOMに更新されます。

高レベルのコンポーネント

高階コンポーネントは、Reactコンポーネントをパラメータとして受け取り、新しいReactコンポーネントを返します。また、高階コンポーネントは基本的にコンポーネントではなく関数です。

高次コンポーネントの使用には、主に4つのシナリオがあります:

  1. プロップの操作
  2. ref 経由でのコンポーネント・インスタンスへのアクセス
  3. コンポーネント・ステートの強化
  4. コンポーネントを他の要素でラップ

パラメータを渡す高階コンポーネント

HOC(....params)

一般的に、高階コンポーネントは汎用ロジックを処理するために高階コンポーネントによって使用され、関連するプロパティをラップされたコンポーネントに渡す、この種の属性プロキシ。 属性プロキシに加えて、高階コンポーネントは継承によって実装することもできます:ロジックの再利用は、ラップされたコンポーネントから継承することによって達成されます。継承によって実装された高階コンポーネントは、レンダリングハイジャックによく使用されます。コードは次のようになります:

function withAuth(WrappedComponent) {
 return class extends WrappedComponent {
 render() {
 if (this.props.loggedIn) {
 return super.render();
 } else {
 return null;
 }
 }
 }
}
  1. 複数の高階コンポーネントを組み合わせると、混乱しやすく、タワゴトに属しますので、属性プロキシを持つ高階コンポーネントを使うようにしましょう。
  2. 重複レンダリングを避けるため、レンダー・メソッドやライフサイクルではなく、コンポーネントの外側で高次コンポーネントを使用します。
  3. ラップされたコンポーネントの静的メソッドを使用する必要がある場合は、それらの静的メソッドを手動でコピーする必要があります。これは、上位コンポーネントが返す新しいコンポーネントには、ラップされたコンポーネントの静的メソッドが含まれていないためです。
  4. Refはラップされたコンポーネントには渡されません。高階コンポーネントの返されたコンポーネントに ref が定義されている場合、それはラップされたコンポーネントではなく、その返されたコンポーネントを指します。ラップされたコンポーネントのrefを取得したい場合は、refを取得するメソッドをカスタマイズし、refプロパティの値を介してこのメソッドをラップされたコンポーネントに渡します。
  5. 親コンポーネントは、主にUI/DOMに関係するコンポーネントです。

React Router

  1. react-routerは、最も基本的なルーティング機能を提供しますが、実際には、直接react-routerをインストールしませんが、アプリケーションが実行される環境に応じてreact-router-domをインストールすることを選択します。
  2. BrowserRouterは、HTML 5の履歴APIを使用して、アプリケーションのUIとURLを同期します。
  3. HashRouterはURLのハッシュを使ってアプリケーションのUIをURLと同期させます。

ルーティングの構成

Link

LinkはReact Routerが提供するリンクコンポーネントです。

<Link to='/'>Home</Link>
<Link to={{
 pathname: '/posts',
 search: '?sort=name',
 hash: '#the-hash',
 state: { fromHome: true }
}}/>

履歴を使用して手動でジャンプすることもできます。

history.push('/posts')
history.replace('/posts')

Redux

Reactは、ビューレイヤーに焦点を当て、大規模なアプリケーションの場合は、状態の管理が良好ではないので、Reduxを使用する必要性は、グローバルな状態管理を実施するために

redux3つの原則

  1. 独自のデータソース
  2. state読み取り専用、アクションによる変更
  3. reducer純粋な関数

mapStateToProps

mapStateToPropsは、その名前が示すように、ストアの状態をコンポーネントのpropsに変換します。mapStateToPropsはstateパラメータを受け取りますが、コンテナコンポーネントのpropsオブジェクトを表す2番目のパラメータを使用することもできます。

// ownProps はコンポーネントのpropsオブジェクトである
function mapStateToProps(state, ownProps) {
 //...
}

mapDispatchToProps

ストアからディスパッチパラメータを受け取り、状態を変更するアクションリクエストを開始します。

redux自体は非同期リクエストを処理できないので、ミドルウェアを使う必要があります。

redux-sagaはgenerate構文を使用し、非同期リクエストを実装するためにcallやputなどのメソッドを提供しています。

状態の設計

間違いその1:状態設計の基礎としてAPIを使うこと

間違い2:状態を設計するための基礎としてUIを使うこと

正しい方法:状態をデータベースのように設計すること

Read next

公式シリーズ - リートコード連鎖表のポイント&問題まとめ

序文\n\n\n\n\n\n\n\n\nアルゴリズムコレクションを提供するJava版の剣\n githubアドレス\nアルゴリズムのブラッシュアップの準備を始めた当初は、本当に難しく、10個中9個のトピックが知られていないと感じました。というのが正直な感想です。

May 11, 2020 · 17 min read