reactのレンダリング(feat.useref,Closer)

10599 ワード

🚍 だからあなたがどう考えても私は知っています。


以前、ReactがDOMを更新する過程を整理したとき、私は自分の反応に自信を持ちすぎた.
しかし、最近気づいたのは、私はただ軽く食べて反応を知っただけだ.
最近作成されたREACTのUseEffect非同期呼び出しや依存も感じられますが、本当に知っているときが一番危険なときだということが、開発の世界だということをだんだん理解してきました.
要するに、今回悟ったのは、reactのuserefとlandering過程の小さな理解を忘れる前に、整理しておくことです.

🚍 1. useRef?



公式ファイルによると、userefは初期値がパラメータの変更可能なオブジェクトである.
ここで、変更可能とは、初期値が変更可能であることを意味する.
一般変数とは異なり、userefに格納されている値は、前述したようにライフサイクル全体で保持されます.
すなわち、素子関数を呼び出すたびに通常の変数のように新しい値に初期化されるのとは異なり、userefとして格納された値は、メモリにキャッシュのように保存され、変更される前にこの値を参照し続けます.(reactアプリ全体に記録されているCloserの中で取り直していると考えれば分かりやすいはず)
しかし、ここには少し注意が必要です.

userefを呼び出して返されるオブジェクトは、メモリに格納された純粋なJavaScriptオブジェクトです.
ただし、refが返すオブジェクトの内部値は可変です.では、内部値が変化するとreactionはそれを検出して再レンダリングしますか?
いいえ.
内部値が変更されても、refが返すオブジェクト自体の参照アドレスは変更されません.メモリ内で同じ方法で格納された値を参照し続けるためです.(純粋なjavascriptオブジェクトの内部値と変化する可能性はあります.内部値が変化しても、オブジェクト全体の参照アドレスは変わりません.)
従って、以下の状況を確認することができる.
function App() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  console.log(canvasRef.current) //무슨 결과를 보여줄까?

  return (
    <Main>
      <ImageWrapper>
        <Canvas ref={canvasRef} />
        <img src={Back} alt="" />
      </ImageWrapper>
    </Main>
  );
}
個人的にはReactはJavaScriptとは違う感じでしたが、結局ReactのベースはJavaScriptでした.すべてのことはJavaScriptの動作原理に従って理解しなければならない.
以前に学習したreactが関数コンポーネントを呼び出すと、babelはそれをcreateElement呼び出しに変換し、それによって生成された結果jsxオブジェクトをrenderのパラメータに入れて仮想domを形成し、domを操作することによって色を塗る.このような長い過程は先に省略しましょう.
何なのかはわかりませんが、アプリを呼べば何が起こるのでしょうか?
呼び出し関数であるため、タグ分解後にASTを作成し、それに基づいて実行コンテキストを作成してcallstekに渡すプロセスがあります.
実行コンテキストでは、userRefによって返される純粋なJavaScriptオブジェクトである定数canvasRefに割り当てられた値を開始しようとします.この時点まで{current:null}に初期化された状態であった.
次にscopeチェーンに上がり、windowでコンソールpropertyを検索し、prototypeチェーンでオブジェクト内でlogメソッドを検索して呼び出します.
呼び出されたlog関数も実行コンテキストを作成し、パラメータとして渡します.currentをコンソールウィンドウに配置します.
この瞬間の遊説currentはnullなので、当然nullが印刷されます.
その後、returnで何かを返し、styledcomponent、すなわち関数を返します.
この関数はpropsのchildrenを介して内部の存在を伝達する.これは別の関数コンポーネントであるか、reactが提供するhtml要素propsオブジェクトである可能性があります.
html要素propsオブジェクトとは、hiや設定などの意味です.これは、ファイルを変換するときにhtmlのbutton要素がpropsを持つオブジェクトに変換されることを意味します.

要するに、Canvasもstyledcomponent、すなわち関数であり、パラメータでrefを受信して伝達する.実際、styledcomponent自体も内部構造を表示し、propertyを返す純html要素のattributeに受信した値を配置しています.ここでは「canvas」になります.
要するに、Canvasに渡されるrefが先ほど述べたuserRefの戻りオブジェクトであることが重要である.
 const canvasRef = useRef<HTMLCanvasElement>(null);

.
.
.
return (
.
.
.
<Canvas ref={canvasRef}/>
)
関数要素にも閉包があるため、このときの定数、canvasRefは戻り値の内部にある「Canvasref={canvasRef}」参照に存在する.
先ほど述べたcreateElement関数が呼び出され、この戻り値を使用するとrefがcanvasRefに関連付けられるため、メモリに格納される、すなわち、メモリモジュールに格納されるcanvasRef定数のオブジェクト内部電流が更新される.
すなわち、関数コンポーネントのボディでuserefの戻りオブジェクトを使用しようとすると、エラーが発生します.
値を一度に戻してマウントしたタスクは、現在再初期化されているため、この値を使用できます.
このとき,関数素子内の戻り値自体のコードも,その瞬間にcanvasRef更新前のスナップショットを記憶するため,そのまま使用するとエラーとなることに注意する.
したがって、通常は、新しく導入されたオプションのリンクを使用することが望ましい.
function App() : JSX.Element {
  const canvas = useRef<HTMLCanvasElement>(null);
 
  return (
    <Main>
      <button
        onClick={() => {
          const ctx = (canvas.current as HTMLCanvasElement)?.getContext("2d");
          // ctx?.fillRect(25, 25, 100, 100);
          // ctx?.clearRect(45, 45, 60, 60);
          ctx?.strokeRect(25, 25, 100, 100);
        }}
      >
        draw
      </button>
      <ImageWrapper>
        <Canvas id={"canvas"} ref={canvas} />
        <img src={Back} alt="" />
      </ImageWrapper>
    </Main>
  );
}
上のbuttonエレメントのonClickの疑問符ロールは、「前の値が存在する場合は、次のナビゲーション、そうでない場合はundefined」です.
あなたに作ってあげます.つまりifゲートのようにctxがあれば、それを使って、後でやらせるようにすることができます.
この場合、undefinedでも関連のないコンテキストで使用する必要がある点に注意してください.たとえば、onClick関数内でundfinedでコード行を計算しても、あまり問題はありませんが、このオプションのリンク値をどこかに保存したり、変数を使用する動作が定義されていない場合は、問題である場合は使用しないでください.

n/a.結論


書くときに整理すると言うのがもっと冗長に感じました(…)
しかし、今日私が悟った内容は以下の通りです.
  • 関数要素も関数であるため、初期にドアに戻る前に運転時に同じ動作をしていた.
  • すなわち実行順に従って,問題が発生する余地があるかどうかを事前に考えて参照する.
  • userEffectに示すように、内部状態値が非同期で実行される関数によって変更された場合に、再有効にすると、関数要素が再実行されます.再実行時にステータス更新のために参照できる論理がある場合は、常に最初の実行時にコードが読み込まれたときにコンテキストが参照できない場合にコードを記述することを考慮してください.