React v16.9の変更点
少し前に約3ヶ月ぶりのマイナーバージョンアップが来ていたので、変更点を確認。公式に沿っているので、特に目新しい情報が記載されているわけではありません。あしからず。
非推奨項目
アンカータグの"javascript:"
アンカータグにjavascript:
を使う記述が非推奨になりました。
// Warning!
const App = () => <a href="javascript: alert('hello')">click</a>
使用はできますが、v16.9ではコンソールに警告が表示されます。dangerouslySetInnerHTML
を使えば警告は表示されませんが、あえて使用するケースも少ないでしょう。
Factory Component
renderメソッドでオブジェクトを返すfactoryコンポーネントが非推奨になりました。
function FactoryComponent() {
return { render() { return <div />; } };
}
動的にクラス名を作成する場合など、コンポーネントを作成する処理を記述する用途で利用されていたようです。
ライフサイクルメソッド
以下のライフサイクルメソッドがリネームされました。
- componentWillMount→UNSAFE_componentWillMount
- componentWillReceiveProps→UNSAFE_componentWillReceiveProps
- componentWillUpdate→UNSAFE_componentWillUpdate
リネームされたメソッドは、16.9と今後リリースされる17.xでも機能します。今あるコードを自動でリファクタリングしたい場合には、公式で示されている以下のコマンドを実行します。
npx react-codemod rename-unsafe-lifecycles
Async act()
過去記事で取り上げたように、React Hooksのテストを行う際にact()
が導入されました。このユーティリティメソッドが非同期処理に対応するようになりました。
await act(async() => {
});
機能の追加
React.Profiler
React v16.5で追加されたボトルネックを調査するReact DevToolsの大規模アプリケーション版だそうです。要はレンダリング時のコストを把握するAPIですね。
メモ化など、レンダリング時のボトルネックを改善するために利用します。
使用方法
Profiler
をインポートし、ボトルネックを調査したい場所にラップします。コンポーネントにはid
とonRender
を定義します。後者は再レンダリングが発生するたびにコールされるコールバック関数で、レンダリングにかかった時間などの情報を受け取ります。
<Profiler id="Check" onRender={onRenderCallback}>
<Component />
</Profiler>
onRender
コールバック関数は以下の引数を受け取ります。
function onRenderCallback(
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime,
interactions
) {
// ログの書き出しなど
}
- id - Profilerで指定したid
- phase - フェーズ状態。"mount"か"update"が格納(下記参照)
- actualDuration - 更新のレンダリングに要した時間。通常、メモ化すると必要部分のみを更新するため、マウント後以降はこの値が減少していくのが理想的
- baseDuration - メモ化せずにツリー全体をレンダリングする場合の予想時間。actualDurationとの対比に使われると思われます。
- startTime - 現在の更新レンダリングを開始したときのタイムスタンプ
- commitTime - Reactが現在の更新をコミットしたときのタイムスタンプ
- interactions - Interaction tracingのセット。指定しないと空のSet配列が返る
Reactはrenderとcommitという2つのフェーズを持っています。renderフェーズは変更を行う必要があるかを決定し、その結果を以前の内容と比較します。commitフェーズは、実際にDOMへの挿入や削除などの変更になります。
出力例
以前解説したReact.memo
のサンプルをProfiler
でラップし、連続レンダリングしたものを単に出力してみると、例えば以下のような値が出力されます。
actualDurationとbaseDurationに注目します。100回再レンダリングし、メモ化前後で比較してみました(抜粋)。実際に再レンダリングされるコンポーネントは2の累乗あります。
メモ化しない場合は更新のたび追加以外のコンポーネントも更新されるため、徐々にactualDurationが増えていきます。尚、Profiler
はコストがかかるため、プロダクション時は自動で無効になるそうです。