aloerina01 / til

1日1つだけ強くなる
6 stars 0 forks source link

2019/01/30 ReactHooksのコードリーディング #96

Open aloerina01 opened 5 years ago

aloerina01 commented 5 years ago

昨日の続き。

FiberSchedulerによってbeginWork -> completeWork -> commitWork が実行されることところまでは読み解いた。

react/ReactFiberBeginWork.js at master · facebook/react

function createWorkInProgressHook(): Hook {
  if (workInProgressHook === null) {
    // This is the first hook in the list
    if (firstWorkInProgressHook === null) {
      currentHook = firstCurrentHook;
      if (currentHook === null) {
        // This is a newly mounted hook
        workInProgressHook = createHook();
      } else {
        // Clone the current hook.
        workInProgressHook = cloneHook(currentHook);
      }
      firstWorkInProgressHook = workInProgressHook;
    } else {
      // There's already a work-in-progress. Reuse it.
      currentHook = firstCurrentHook;
      workInProgressHook = firstWorkInProgressHook;
    }
  } else {
...

WIPのhookをつくるとき、ReactFiberHooks.jsスコープの変数に対して存在チェックを掛けてなければcreate&setしてて、なんかキモチワルイ。個人的にはこうだと自然に感じる。

cretateAndSetHook(workInProgress: Fiber): Hook {
  if (!workInProgress.hook) {
    workInProgress.hook = createHook();
  }
  return workInProgress.hook;
}

でもHookのソースって、Fiber系ロジックのような「Fiberインスタンスを引数で受けて、それに対して操作する」感じのロジックではないんだよなー。なのでこの案はどこかに破綻があるのかもしれない。

renderWIthHookの中でcurrentlyRenderingFiber = workInProgressとかしてるし。 雰囲気で見るに、beginWork -> completeWorkの実行過程ではFiberHook.jsスコープの変数にworkInProgresssのものが格納され続けて、それをresolveCurrentlyRenderingFiberとかで参照しながらHook処理を行っていく感じなんだと思う。

漠然とHookインスタンスがComponentのプロパティとして生えてるようなのをイメージしてたせいで理解に苦しんだけど、そういうことではないんだね。

なので以前 https://github.com/aloerina01/til/issues/79 でやったようなHook用のstateやsetterを生やすのは間違い(この答え合わせをしたかったのにえらく時間かかったわ…)

aloerina01 commented 5 years ago

react/ReactFiberScheduler.js at master · facebook/react

renderRootの呼び出し元たどっためも

intaractiveUpdates -> performWork -> perfoemWorkOnRoot -> renderRoot

retryTimedOutBoundary -> scheduleWork -> requestWork -> perfoemWorkOnRoot -> renderRoot

captureCommitPhaseError -> scheduleWork -> requestWork -> perfoemWorkOnRoot -> renderRoot