React state hookを深く理解する
12516 ワード
まず問題を見てください.下のコンポーネントの中で3回のコンポーネントは初めて「set Counter」ボタンをクリックし、 は「set Counter」ボタンを二回クリックしました. 第3回「set Counter」ボタンをクリックしたが、 正解したら、直接に賞賛して前のページに戻ることができます.正解がないと残りの内容を読む時間がかかります.
一、キューの更新
実は、各state Hookは更新待ち行列に関連しています.
1.2複数のジョブキュー
各state Hookは、タスク・キューに対応しており、1つのコンポーネントには複数のタスク・キューが含まれる可能性がある.各タスク・キューは互いに独立している. 各ジョブキューの更新関数の実行順序は、ジョブキューの作成順序、すなわち
二、不精計算
三、バッチ処理バッチ処理は、最大一回のre−renderをトリガし、一つのバッチ処理には複数のタスクキューが含まれてもよい. バッチの処理は、コールバック関数内の同期コードしか処理できません.非同期コードは新しいバッチとして処理されます. 四、レンダリングをスキップする
4.1直ちに計算する
上に述べたのはすべて怠惰な計算です.実はReactはすぐに計算しています.Reactは直ちに関数を更新します. 前回の計算の現在 前回の計算 4.2怠惰計算
不精計算とは上記の通りです.怠惰な計算中に最終的に計算された
不精計算による問題は、一次構成要素
Note that React may still need to render that specific component again before bailing out.That shout't be a concern because React won't unnecessary go“deeper”into the tree.If you’extringtivent.
4.3直ちに自動転怠計算を計算する
1つのバッチ処理において、直ちに計算して
参照
gitHubからノートを整理する: 解読React state hook State Hook
Counter
の「set Counter」ボタンを押すと、コンソール出力は何ですか?function Display({ counter }) {
console.log('Display.render', counter);
return {counter}
}
function Counter() {
const [counter, setCounter] = useState(1);
console.log('Counter.render', counter);
return (
<>
>
)
}
正しい答え:state
は2になり、一回のre-renderをトリガします.出力:Counter.render 2
Display.render 2
state
は変化していませんが、もう一回のコンポーネントCounter
re-renderをトリガしました.しかし、トリガコンポーネントDisplay
re-renderがありません.出力:Counter.render 2
Display.render 2
Counter.render 2
state
は変更されておらず、re-renderもトリガされていない.一、キューの更新
実は、各state Hookは更新待ち行列に関連しています.
setState
関数を呼び出すたびに、Reactは更新関数をすぐに実行するのではなく、更新関数を更新キューに挿入し、Reactはre-renderを配置する必要があるとReactに教えます.function Counter() {
const [counter, setCounter] = useState(0);
console.log('Counter.render', counter);
return (
<>
>
)
}
まず「Add」ボタンを押してから「set Counter」ボタンをクリックして出力を見てください.Click event begin
Click event end
update 1
update 2
Counter.render 2
Display.render 2
イベントハンドラを実行中に更新関数は実行されませんでした.主に性能の最適化のために、複数のsetState
関数がコールされる可能性があるからです.1.2複数のジョブキュー
各state Hookは、タスク・キューに対応しており、1つのコンポーネントには複数のタスク・キューが含まれる可能性がある.
useState
を呼び出す順序に依存する.function Counter() {
console.log('Counter.render begin');
const [counter, setCounter] = useState(1);
const [counter2, setCounter2] = useState(1);
return (
<>
counter1: {counter}
counter2: {counter2}
>
)
}
setCounter
に対応するジョブキューの更新関数は、setCounter2
に対応するジョブキューの更新関数よりも常に先行して実行される.二、不精計算
state
が必要なときだけ、Reactは最新のstate
値を計算します.つまり、useState
が再実行されるまで更新キューの更新関数が実行されます.また、同じ更新キューの複数の更新関数は順次実行され、前の更新関数の出力は次の更新関数の入力として使用されます.function Display({ counter }) {
console.log('Display.render', counter);
return {counter}
}
function Counter() {
console.log('Counter.render begin');
const [counter, setCounter] = useState(0);
console.log('Counter.render', counter);
return (
<>
>
)
}
まず「Add」ボタンを押してから「set Counter」ボタンをクリックして出力を見てください.Click event begin
Click event end
Counter.render begin
update 1, prev=1
update 2, prev=10
Counter.render 20
Display.render 20
この時先に実行されたレンダリング関数を発見し、更新関数を実行します.二番目の更新関数の参照は、最初の更新関数の戻り値です.三、バッチ処理
useState
を再実行した場合にのみ、更新関数が実行され、すなわちレンダリング関数が再実行された場合にのみ、state
に変化があるかどうかが分かる.Reactはいつまたレンダリング関数を実行しますか?一般的には、イベント処理関数(ユーザインタラクション、ネットワーク)でsetState
を呼び出し、Reactはバッチ処理でコールバック関数を実行します.コールバック関数が実行された後、re-render
の要求がトリガされると、Reactはre-render
をトリガする.function Counter() {
console.log('Counter.render begin');
const [counter1, setCounter1] = useState(0);
const [counter2, setCounter2] = useState(0);
return (
<>
counter1={counter1}
counter2={counter2}
>
)
}
「set Counter」ボタンをクリックして、出力を見てください.Counter.render begin
function Display({ counter }) {
console.log('Display.render', counter);
return {counter}
}
function Counter() {
console.log('Counter.render begin');
const [counter, setCounter] = useState(0);
return (
<>
>
)
}
は「set Counter」ボタンをクリックして、出力を見てください.Counter.render begin
Display.render 10
Counter.render begin
Display.render 20
は2回のバッチ処理をトリガします.state
の値が変化していないと、Reactはコンポーネントを再レンダリングしないことを知っています.しかし、上からReactはuseState
を再実行する時だけstate
の値を計算すると分かりました.最新のstate
を計算するためにre-renderをトリガする必要がありますが、state
は不変でレンダリングコンポーネントがない場合、卵があるかそれとも先に鶏があるかのようです.Reactは2つのポリシーでスキップして再レンダリングします.4.1直ちに計算する
上に述べたのはすべて怠惰な計算です.実はReactはすぐに計算しています.Reactは直ちに関数を更新します.
state
値が不変であれば、re-render
をトリガしない.state
値が変化したら、怠け者ローディングポリシーに移行する.state
が変化していないか、または前回のstate
である場合は、すぐに実行されるポリシーを用いて更新関数を呼び出す.state
は初期stateである.function Counter() {
console.log('Counter.render begin');
const [counter, setCounter] = useState(1);
return (
<>
counter={counter}
>
)
}
は「set Counter」ボタンをクリックして出力を見てください.Click event begin
update
Click event end
はReactデフォルトは即時実行ポリシーを採用すると説明しています.state
不変function Counter() {
console.log('Counter.render begin');
const [counter, setCounter] = useState(1);
return (
<>
counter={counter}
>
)
}
は2回以上の「set Counter 2」ボタンをクリックして(前回の計算結果を作成するのはstate
です.)、もう一度「set Counter」ボタンをクリックして出力を見てください.不精計算とは上記の通りです.怠惰な計算中に最終的に計算された
state
に変化が発見されなかった場合、Reactはコンポーネントのサブコンポーネントを選択しない、すなわちこのときはコンポーネントレンダリング関数が実行されたが、コンポーネントのサブコンポーネントはレンダリングされない.function Display({ counter }) {
console.log('Display.render', counter);
return {counter}
}
function Counter() {
console.log('Counter.render begin');
const [counter, setCounter] = useState(1);
return (
<>
>
)
}
「set Counter 2」ボタンを二回クリックして、出力を見てください.Counter.render begin
Display.render 2
Counter.render begin
第2のクリックは、親コンポーネントre-render
をトリガしたが、サブアセンブリDisplay
はre-render
を有しない.不精計算による問題は、一次構成要素
re-render
を多くトリガするだけであるが、これは一般的に問題ではない.React useState APIドキュメントも言及しました.Note that React may still need to render that specific component again before bailing out.That shout't be a concern because React won't unnecessary go“deeper”into the tree.If you’extringtivent.
4.3直ちに自動転怠計算を計算する
1つのバッチ処理において、直ちに計算して
state
が変化すると、すぐに怠惰計算モードになります.つまり、後のすべてのジョブキューの更新関数は実行されません.function Counter() {
console.log('Counter.render begin');
const [counter, setCounter] = useState(1);
return (
<>
counter={counter}
>
)
}
「set Counter」ボタンをクリックして、出力を見てください.Click event begin //
update 1 // state state, , 1
update 2 // 1 state, , 2, state ,
Click event end
Counter.render begin
update 3
2
を実行した後にstate
が変化しました.Reactは直ちに怠惰負荷モードになりました.後の更新関数はすぐに実行されなくなりました.参照
gitHubからノートを整理する: