…を待つ.どのように反応する.USENTの仕事?


だから反応フックはしばらくの間リリースされており、彼らは素晴らしいです!私は生産コードでそれらを使用しており、それはすべてがより良く見えます.私がフックを使い続けたので、私はこの魔法がどれくらい働くかについて疑問に思い始めました.
どうやらボストンだけがこの話題になっていたので、私は一人ではなかった.このような素晴らしい話をするためにライアン・フィレンツェとマイケル・ジャクソン(ムーンウォーク伝説ではない)に感謝します.見続けてください、そして、あなたはより多くを学びますuseEffect そして、どのように動作します!

どうやって動くの?


あなたは機能的なコンポーネントを作成し、それを更新することができます状態を追跡する、それにいくつかの反応フックをスローし、それだけで動作します.
私たちの多くは、前にこの例のいくつかのバリエーションを見てきました.

1つの不動産


import React from "react";

const App = () => {
  const [count, setCount] = React.useState(1);

  return (
    <div className="App">
      <h1>The infamous counter example</h1>
      <button onClick={() => setCount(count - 1)}>-</button>
      <span style={{ margin: "0 16px" }}>{count}</span>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
};

export default App;
👏 👏 👏 動く!

大丈夫、しかしどのようにそれは魔法を行うのですか?この動画を見るReact.useState ライン.それはとても読みやすいので、私は決してそれを疑った.私には、count 値と関数setCount そして、それは私が通過したデフォルト値でカウントを初期化するでしょうuseState . 別のときに何が起こるかReact.useState 写真に?

つのUSENT ,ハハha


カウントドラキュラ誰か?
const App = () => {
  const [count, setCount] = React.useState(1);
  const [message, setMessage] = React.useState("");

  const adder = () => {
    if (count < 10) {
      setCount(count + 1);
      setMessage(null);
    } else {
      setMessage("You can't go higher than 10");
    }
  }

  const subtracter = () => {
    if (count > 1) {
      setCount(count - 1);
      setMessage(null);
    } else {
      setMessage("You can't go lower than 1, you crazy");
    }
  }

  return (
    <div className="App">
      <h1>The infamous counter example</h1>
      <button onClick={subtracter}>-</button>
      <span style={{ margin: "0 16px" }}>{count}</span>
      <button onClick={adder}>+</button>
      <p>{message}</p>
    </div>
  );
};
ユーザーが1 - 10の境界の外に行こうとしているときはいつでも、我々はメッセージを示しています

我々のコンポーネントでは、2つの破壊された配列がありますReact.useState 異なるデフォルト値を持つフック.おっ、今、我々はすべての魔法になっている.
そうすれば削除React からReact.useState 「USENTは定義されていません」というreferenceerrorを得るべきです

我々自身を実行しましょうuseState 関数.

USENT関数のリバースエンジニアリング


エーuseState 関数は値とその値を設定する関数を持っています
このような
const useState = (value) => {

  const state = [value, setValue]
  return state
}
まだ定義されていないので、我々はまだリファレンスエラーを得ていますsetValue . setValueは関数を使用しているため、useStateカウントuseState : const [count, setCount] = React.useState(1);呼び出しsetCount : setCount(count + 1);を作成するsetValue 関数はこれ以上エラーにならない- and + ボタンが動作しません.
const useState = (value) => {
  const setValue = () => {
    // What do we do in here?
  }

  const state = [value, setValue]
  return state
}
デフォルト値を変更してくださいuseState 更新しますcount 👍🏽. 少なくとも何かが働いている😂.

地獄SetValueが何をするかを考え出すために動いています。


我々が見るときsetCount それは何らかの値の再割り当てをしています、そして、それはRerenderに反応します.それで、それは我々が次にすることです.
const setValue = () => {
  // What do we do in here?
  // Do some assigning
  // Rerender React
}
我々は、我々に新しい価値議論を渡しますsetValue 関数.
const setValue = (newValue) => {
  // What do we do in here?
  // Do some assigning
  // Rerender React
}
でもどうするのnewValue 内部setValue 機能?
const setValue = (newValue) => {
  // Do some assigning
  value = newValue // Does this work?
  // Rerender React
}
value = newValue しかし、それはカウンタの値を更新しません.なぜ?私はconsole.logsetValue と外部setValue これは我々が見るものです.

私はページをリフレッシュした後.countを1に初期化し、メッセージをNULLに初期化する.私はクリック+ ボタンと我々は2にカウント値の増加を参照してください、それは画面上のカウントを更新しません.🤔 多分私は手動でカウントを更新するには、ブラウザをレンダリングする必要がありますか?

ブラウザを手動で再レンダリングするJanky方法を実装する


const useState = (value) => {
  const setValue = (newValue) => {
    value = newValue;
    manualRerender();
  };
  const state = [value, setValue];
  return state;
};
.
.
.
const manualRerender = () => {
  const rootElement = document.getElementById("root");
  ReactDOM.render(<App />, rootElement);
};

manualRerender();
これはまだブラウザのカウントを更新しません.何か
私は少しの間これで動けなくなりました、そして、現在、私は理由を知っています.ましょうconsole.log 我々はそれを作成した後、右の状態.
const state = [value, setValue];
console.log(state)
我々の呼び出しuseState 最初のレンダリングを行います.[1, setValue()]そして、我々の第2の呼び出しにuseState 次のようにレンダリングします.[null, setValue()]結果:

これを少しよりよく視覚化するのを助けるために、我々がスクリーンを何回レンダリングするかについて数えるために、レンダリングトラッカーを加えましょう.
let render = -1

const useState = (value) => {
  const setValue = (newValue) => {
    value = newValue;
    manualRerender();
  };
  const state = [value, setValue];
  console.log(++render)
  console.log(state)
  return state;
};

どうやってsetValue 関数はどの値を更新するか知っていますか?したがって、我々はそれを追跡する方法が必要です.これを行うには、配列やオブジェクトを使用できます.私は、オブジェクトの赤い錠剤を選びます.
外部useState 関数は、オブジェクトを作成するstates
const states = {}
内部useState 関数はstates オブジェクト.キー/値対を割り当てるためにブラケット記法を使いましょう.states[++render] = stateまた、別の変数を作成するつもりですid それは、私たちが取り出すことができるように、レンダリング値を格納します++render 括弧内.
次のようになります.
let render = -1;
const states = {};

const useState = (value) => {
  const id = ++render;

  const setValue = (newValue) => {
    value = newValue;
    manualRerender();
  };
  const state = [value, setValue];
  states[id] = state;
  console.log(states);
  return state;
};
私たちのstates オブジェクトのように見える?
states = {
  0: [1, setValue],
  1: [null, setValue]
}
それで、我々がクリックするとき、我々が得るボタンを加えて、引いてください.何も再び.だってねvalue = newValue まだ何もしていない.
しかし、起こっている何かが、あります.あなたがコンソールを見るならば、あなたは我々が我々の我々に同じ配列を加えるのを続けるボタンの1つをクリックするたびに、それがわかるでしょうstates オブジェクトですがcount がインクリメントされず、メッセージがまだNULLである.
So setValue 探す必要があるvalue , 次に、newValue to value .
const setValue = (newValue) => {
  states[id][0] = newValue;
  manualRerender();
};
それから、我々はキーを更新するだけであることを確認したいです:0と1useState 場所.
だから頭の下にmanualRerender 関数を呼び出してrender そして- 1に再署名します
const manualRerender = () => {
  render = -1;
  const rootElement = document.getElementById("root");
  ReactDOM.render(<App />, rootElement);
};
setValueを呼び出すたびに、これはmanualRerender 機能設定render 先頭へ戻る
最後に、オブジェクトが存在するかどうかを確認するチェックを追加します.その場合は、オブジェクトを返します.
if (states[id]) return states[id];
今、我々は再び仕事!

Phewそれは非常に単純なアプローチですuseState . 舞台裏で起こるより多くのトンがあります、しかし、少なくとも、我々はそれがどのように働くかという大まかな考えがあります、そして、我々は少しそれをわかりました.
すべてのコードを見てみて、それがすべての作品の精神的なモデルを試してみてください.
このヘルプ😊