Share
Embed
Transcript
21 slides
-
Profile Name: ユウト Field: Web Developer Blog: yossy.dev SNS /
Youtube: @yossydev 2 -
Agenda 1. 高速化のポイント 2. key, ref の予約語をprops からの削除 3. public
api であるcreateElement 後のprops の上書き 4. 実装を見る 3 -
高速化の要因 props をクローンする必要がなくなった ではなぜprops をクローンする必要があったのか 1. key, ref の予約語をprops からの削除
2. public api であるcreateElement 後のprops の上書き 6 -
1. key, ref の予約語をprops から削除すること: key とref key: リスト内の要素を一意に識別するためのプロパティ ref:
コンポーネントのdom 動作を行うことができるプロパティ // key const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => ( <li key={number.toString()} ref> {number} </li> )); // ref const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children} </button> )); 8 -
1. key, ref の予約語をprops から削除すること 問題点 key とref をprops で渡さないようにする必要があった。
for (propName in config) { if ( hasOwnProperty.call(config, propName) && propName !== 'key' && (enableRefAsProp || propName !== 'ref') ) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { props.ref = coerceStringRef( config[propName], ReactCurrentOwner.current, type, ); } else { props[propName] = config[propName]; 9 -
1. key, ref の予約語をprops から削除すること 解消方法 React19 からは props.ref でref
にアクセスできるようになるそう 今までは React.forwardRef で囲む必要があった このアップデートによりref の問題は解消できた そしてkey も元々スプレット構文を使わなければクローンはされないようになって いました。 スプレット構文を使わなければjsx 関数の第三匹数に値が入る key の解決 (スプレット構文使用時以外) 10 -
2. createElement がpublic api である createElement とは何か React17 以前で使われていたjsx をdom
に変換するための関数。これは我々開発者が React からimport して使用することもできる // jsx // compiled jsx function Greeting({ name }) { function Greeting({ name }) { return ( return createElement( <h1 className="greeting"> "h1", Hello <i>{name}</i>. Welcome! { className: "greeting" }, </h1> "Hello ", ); createElement("i", null, name), } ". Welcome!", ); } 12 -
2. createElement がpublic api である ユーザーによるprops の上書き ユーザーがprops の上書きができてしまうので、予期しないバグが起きる恐れがある。 const
props = { className: "my-div" }; const element2 = React.createElement("div", props); props.className = "my-div-changed"; console.log(element2.props.className); // 'my-div-changed' 13 -
2. createElement がpublic api である React17 以降 createElement ではなくjsx 関数が使われるようになった。(React17
におけるJSX の新し い変換を理解する) // jsx // compiled jsx function Greeting({ name }) { function Greeting({ name }) { return ( return _jsxs("h1", { <h1 className="greeting"> className: "greeting", Hello <i>{name}</i>. Welcome! children: ["Hello ", _jsx("i", { children: name }), ". Welcome!"] </h1> }); ); } } 14 -
2. createElement がpublic api である the new JSX runtime, jsx,
is not a public API 翻訳: 新しいJSX ランタイムjsx はパブリックAPI ではない jsx 関数はpublic api ではないため、ユーザーによるprops の上書きを考慮する必要がな くなった 15 -
2. createElement がpublic api である 疑問点: the new JSX runtime,
jsx, is not a public API react/jsx-runtime からimport して使えるやーーん import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const Foo = () => { return _jsxs( "div", { children: [ _jsx("p", { id: "a", children: "I am foo" }, void 0), _jsx("p", { children: "I am foo2" }, "b"), ], }, void 0, ); }; 16 -
2. createElement がpublic api である 予想: the new JSX runtime,
jsx, is not a public API jsx のコメントを見た感じは、使えないではなく使ってもこっちは知らないよみたいな ニュアンスなのかなと感じています。 /** * Create a React element. * * You should not use this function directly. Use JSX and a transpiler instead. */ export function jsx( type: React.ElementType, props: unknown, key?: React.Key, ): React.ReactElement; 17 -
実装を見てみる 単純にfor 分で回さなくてよくなったので早くなってそう... ?? // Before: config をfor 分で回して条件に一致したconfig だけkey
で抽出してprops のkey に代入している for (propName in config) { if ( ... ) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { ... } else { props[propName] = config[propName]; // After: config を直接props に代入してReactElement に渡している let props; if (enableRefAsProp && disableStringRefs && !('key' in config)) { props = config; 19 -
まとめ 今まではprops をクローンする必要があった 1. key, ref の予約語をprops から削除すること ref はprops
で参照できるようになる、key もスプレット構文を使わなければ問題なし! 2. createElemet 後にprops の上書き React17 からjsx という関数が使われていて、それは我々開発者が使うことを推奨して いないようなので気にしないでヨシッ ! 実装 今までfor...in でぐるぐる回していたところを単純にfor 分で回さなくてよくなった 20