banner
IWSR

IWSR

我永远喜欢志喜屋梦子!

React Hooks: useTransition Reactフック: useTransition

説明#

  1. この記事は v18.1.0 を基に分析されています。
  2. この記事を読むには、まずReact Hooks: hooks 链表React Hooks: useState 分析を読む必要があります。
  3. デバッグは React Hooks: useState 内のキューイングに関するコードに基づいています。

TLNR#

このフックの戻り値である startTransition 関数は、関数内でトリガされるすべての更新を低優先度としてマークし、他の高優先度の更新が優先的に処理されるようにします。

mount フェーズの useTransition#

デバッグコードの useTransition にブレークポイントを設定すると、mount フェーズで mountTransition 関数に入ることがわかります。

function mountTransition(): [
  boolean,
  (callback: () => void, options?: StartTransitionOptions) => void,
] {
  // useStateの記事で説明されているので、ここでは省略します
  // ただし、ここでuseTransitionに対応するフックのインスタンスが存在することがわかります(useStateをベースに実装されているため)
  const [isPending, setPending] = mountState(false);
  // `start`メソッドは変更されません。
  // これが重要な実装であり、以下で分析します
  const start = startTransition.bind(null, setPending);
  // hooksのリストについては、すでに説明されているので省略します
  const hook = mountWorkInProgressHook();
  hook.memoizedState = start;
  return [isPending, start];
}

コードから明らかなように、重要な分析ポイントは startTransition にありますので、その実装を見てみましょう。

// いくつかの重要でないコードを削除しました
function startTransition(setPending, callback, options) {
  // 現在の更新の優先度をキャッシュする変数を作成します
  // この優先度はgetCurrentUpdatePriorityとsetCurrentUpdatePriorityでアクセスできます
  const previousPriority = getCurrentUpdatePriority();
  setCurrentUpdatePriority(
    // 現在の優先度とContinuousEventPriorityを比較し、より優先度の高いものを現在の優先度として設定します
    higherEventPriority(previousPriority, ContinuousEventPriority),
  );
  // ここではuseStateのdispatch関数を呼び出すことで、より高い優先度の更新インスタンスを作成しています
  setPending(true);
  
  // ReactCurrentBatchConfigの値を直接変更することで、後続の更新の優先度に影響を与えます
  // 具体的なコードは、updateインスタンスの生成時に呼び出されるrequestUpdateLane関数を見ることができます
  const prevTransition = ReactCurrentBatchConfig.transition;
  ReactCurrentBatchConfig.transition = {};
  const currentTransition = ReactCurrentBatchConfig.transition;

  if (enableTransitionTracing) {
    if (options !== undefined && options.name !== undefined) {
      ReactCurrentBatchConfig.transition.name = options.name;
      ReactCurrentBatchConfig.transition.startTime = now();
    }
  }
  // 要するに、上記のReactCurrentBatchConfigへの操作は、setPendingとcallback内で生成されるupdateインスタンスの優先度に影響を与えますが、その優先度は必ずsetPendingの最初の呼び出しで生成されるupdateインスタンスの優先度よりも低いものです
  // そして、低優先度のupdateはステート更新の処理時にスキップされます。これについてもuseStateの記事で言及されています
  try {
    setPending(false);
    callback();
  } finally {
    // ここでリセットして、優先度を元の状態に戻します
    setCurrentUpdatePriority(previousPriority);

    ReactCurrentBatchConfig.transition = prevTransition;

    ...
  }
}

結論#

非常にシンプルなフックで、基本的な原理は、callback 内で生成される更新に低優先度のマークを付け、他の更新を優先的に処理することです。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。