React復号:React Hooks関数のuseState


React16.8+バージョンのリリースでは、hooks関数は新たに追加された大きな機能ですが、実際にはuseState関数は関数コンポーネントにステータスを与えているので、useStateという関数について詳しく説明します.
使用方法:
const [state, setState] = useState(initialState);

reactは関数式プログラミングであるため、上記のコードはよく理解され、useState関数は初期化パラメータinitialStateを受信し、その戻り値は配列で2つのパラメータを解く、stateは初期化state、およびstateを更新する関数setStateである.初期レンダリング中に返される状態(state)は、入力された最初のパラメータ(initialState)の値と同じである.setState関数はstateを更新するために使用されます.新しいstate値を受信し、コンポーネントの再レンダリングをキューに追加します.
setState(newState);

その後の再レンダリングでは、useStateが返す最初の値は、常に更新後の最新のstateになります.
注意:Reactは、setState関数の識別が安定しており、コンポーネントの再レンダリング時に変化しないことを保証します.したがって、useEffectまたはuseCallbackの依存リストからsetStateを安全に省略することができる.
関数更新
新しいstateが以前のstateを用いて計算する必要がある場合、関数はsetStateに渡すことができる.この関数は、以前のstateを受信し、更新後の値を返します.
function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      
      
      
    >
  );
}

「+」および「-」ボタンは、更新されたstateが以前のstateに基づいている必要があるため、関数形式で使用されます.ただし、「リセット」ボタンは、countを常に初期値に戻すため、通常の形式です.
更新関数の戻り値が現在のstateと完全に同じである場合、その後の再レンダリングは完全にスキップされます.
に注意
classコンポーネントのsetStateメソッドとは異なり、useStateは更新オブジェクトを自動的にマージしません.関数式のsetStateと展開演算子を組み合わせて、更新オブジェクトをマージする効果を達成できます.
setState(prevState => {
  //       Object.assign
  return {...prevState, ...updatedValues};
});
useReducerは、複数のサブ値を含むstateオブジェクトを管理するのにより適した別のオプションです.
ふかっせいしょきstateinitialStateパラメータは、コンポーネントの初期レンダリングでのみ機能し、その後のレンダリングでは無視されます.初期stateを複雑な計算で取得する必要がある場合は、初期レンダリング時にのみ呼び出される関数を入力し、関数内で初期stateを計算して返します.
const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

state更新をスキップ
State Hookの更新関数を呼び出し、現在のstateに入力すると、Reactはサブコンポーネントのレンダリングおよびeffectの実行をスキップします.(ReactはObject.is比較アルゴリズムを用いてstateを比較した.)
Reactは、レンダリングをスキップする前にコンポーネントをレンダリングする必要がある場合があります.ただし、Reactはコンポーネントツリーの「深層」ノードを不要にレンダリングしないので、心配する必要はありません.レンダリング中にオーバーヘッドの高い計算を実行した場合は、useMemoを使用して最適化できます.
以上の部分は公式ドキュメントで与えられた内容です.の
次に、useStateに関するいくつかの問題を解析します.
1、コンポーネントに複数の状態が発生した場合はどうすればいいですか?
コンポーネントに複数のステータスが表示されるのは普通です.つまりuseState関数が複数回呼び出されることを意味する.
import React, { useState } from 'react'
function Example () {
    const [name, setName] = useState('cat')
    const [age, setAge] = useState(0)
    const [gender, setGender] = useState('male') 
}

useState()関数が受信するパラメータは、どのようなタイプのパラメータを受信するかを規定していません.初期値としてのみ使用されます.なお、setStateを呼び出す前に送信するのは、現在のデータを前のstateデータとマージして新しい状態を返すことであり、hooks呼び出しsetStateメソッドは、前のstateデータを置換して新しい状態を返すことであり、もちろんhooksはuseReducer()関数を提供し、redux方式でstateを管理する.
開発では,useState()関数が何回呼び出されても,それらは以前は互いに影響を及ぼさず,互いに独立していたことが分かった.この点が重要です.では、これはどのようにしてできたのでしょうか.
reactはuseStateの順序によって規定されます.react実装の内部に配列が宣言され、そのuseState()関数呼び出しの順序でデータが保存されるので、if...Else,forループ,サブ関数でuseState()を呼び出すため,react関数はデータを保存する配列を共有するため,他の関数コンポーネントにも影響を及ぼす.Capture Valueプロパティの生成は、Renderのたびに関数コンポーネントを再実行し、以前に実行した関数コンポーネントについては何もしません.
を使用して、簡単なuseState関数を実装します.
let memoizedState = []; // hooks        
let cursor = 0; //    memoizedState   

function useState(initialValue) {
  memoizedState[cursor] = memoizedState[cursor] || initialValue;
  const currentCursor = cursor;
  function setState(newState) {
    memoizedState[currentCursor] = newState;
    render();
  }
  return [memoizedState[cursor++], setState]; //      state,   cursor   1
}

次にreactがどのように実現されているかを見てみましょう.
(1)Reactでは配列の代わりに単鎖表のような形である.nextですべてのhookを順番に直列に接続します.
type Hooks = {
  memoizedState: any, //          Fiber
  baseState: any, //     initialState,      dispatch    newState
  baseUpdate: Update | null,//         Update ,       ,       update,   react         ,    
  queue: UpdateQueue | null,// UpdateQueue   
  next: Hook | null, // link      hooks,   next      hooks
}

memoizedState、cursorはどこに存在しますか?各関数コンポーネントにどのように対応しますか?
reactはコンポーネントツリー(またはFiber単一チェーンテーブル)を生成し、ツリー内の各ノードがコンポーネントに対応し、hooksのデータはコンポーネントの情報として格納され、コンポーネントとともに誕生し、一緒に死亡することを知っています.
useState終了...