🦾

React Compilerで出力されるc(number)について

2024/06/10に公開

Intro

React Compilerの出力結果を見ると、const $ = _c(1);というコードを見たことがあると思います。
このブログでは、この_c<number>がReact Compiler側でどのように作られているのかをみていきます。

内容

https://github.com/facebook/react/blob/f5af92d2c47d1e1f455faf912b1d3221d1038c37/compiler/packages/react-compiler-runtime/src/index.ts#L21-L37

↑ まず実装はこんな感じです。引数に受け取ったnumberの値分の配列をnew Arrayで作って、それを$という変数に代入しています。そしてその$をreturnしています。

returnする前にfor分で$[ii]に対して$emptyを代入していますが、$[ii]に代入しているのはSymbol.for("react.memo_cache_sentinel")になっていて、キャッシュ済みかどうかを判定できるようにしています。

if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
    t0 = <div>Hello World</div>;
    $[0] = t0;
} else {
    t0 = $[0];
}

↑ 最初は$[ii]Symbol.for("react.memo_cache_sentinel")になっているのでtrueになります。そしてこのタイミングで$[ii] = t0;というように上書きしています。そのため次回以降はキャッシュされた値が出力されます。

_がつく理由

出力コードを見ると、cは_cのようになっていると思います。これはprogram.scope.generateUidIdentifierを使用しているためです。https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#generating-a-uid

https://github.com/facebook/react/blob/f5af92d2c47d1e1f455faf912b1d3221d1038c37/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts#L251

例えば以下のようにuidをbに変更してみるとどうなるでしょうか👀

code

const useMemoCacheIdentifier = program.scope.generateUidIdentifier("b");

この状態でyarn testを実行してみます。

log

useMemoCacheIdentifier: { type: 'Identifier', name: '_b' }

- import { c as _c } from "react/compiler-runtime";
+ import { c as _b } from "react/compiler-runtime";
  function foo(props) {
-   const $ = _c(4);
+   const $ = _b(4);

ちゃんとcがbになって出力されているようです。

まとめ

なんとなく_c<number>について理解できたのではないでしょうか。
具体的にcがどのようにコンパイル時に使われているのかまではそのうち書きます!🤞

Discussion