React18 beta の新機能を紹介する【Automatic Batching (自動バッチ処理)編】
最近 React18beta がリリースされました。今回は、React18 で追加される大きな新機能の中から「Automatic Batching(自動バッチ処理)」についてご紹介します。
React18 の新機能
React18 で追加される大きな新機能は下記の通りです。
- Concurrent Rendering(並行レンダリング)
- SSR support for Suspense(サスペンスの SSR サポート)
- Automatic Batching(自動バッチ処理)
- Selective hydration(選択的ハイドレーション)
- Built-in Cache(組み込みキャッシュ機構)
今回は自動バッチ処理を React17 と比較してみたいと思います。
インストール
create-react-app ${プロジェクト名}
npm install react@beta react-dom@bet
AutomaticBatching(自動バッチ処理)を検証
今までは関数内でのみバッチ処理を行っていました。
しかし、React18 からはどこから発生したか関係なくすべてのレンダリングがバッチ処理されるようになります。
creat-react-app のコードを流用して実装します。
React18 を導入するためには ReactDOM.render から ReactDOM.createRoot への移行が必須です。
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
↓
const container = document.getElementById("root");
const root = ReactDOM.createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
検証用のコードです。
onClick で clickHandler 関数を実行します。
clickHandler 関数は setTimeout で非同期でステートを更新します。
const App = () => {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
const [count3, setCount3] = useState(0);
const clickHandler = () => {
setTimeout(() => {
setCount1((count) => count + 1);
setCount2((count) => count + 1);
setCount3((count) => count + 1);
}, 500);
};
console.log("rendering!!!");
return (
<div className="app">
<header className="app-header">
<img src={logo} className="app-logo" alt="logo" />
<p>{count1}</p>
<p>{count2}</p>
<p>{count3}</p>
<div className="push" onClick={clickHandler}>
push
</div>
</header>
</div>
);
};
export default App;
以前の React であれば非同期処理内のステート更新は別々のレンダリングでした。
しかし、React18 ではバッチ処理が行われ、一回でレンダリングしているのがわかります。
React17
React18
バッチ処理をオプトアウトできる API
flushSync でバッチ処理をオプトアウトできます。
import { flushSync } from "react-dom";
const App = () => {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
const [count3, setCount3] = useState(0);
const clickHandler = () => {
setTimeout(() => {
// setCount1だけバッチ処理されない
ReactDOM.flushSync(() => {
setCount1((count) => count + 1);
});
setCount2((count) => count + 1);
setCount3((count) => count + 1);
}, 500);
};
console.log("rendering!!!");
return (
<div className="app">
<header className="app-header">
<img src={logo} className="app-logo" alt="logo" />
<p>{count1}</p>
<p>{count2}</p>
<p>{count3}</p>
<div className="push" onClick={clickHandler}>
push
</div>
</header>
</div>
);
};
export default App;
React18
flushSync のコールバック関数内に切り出せばバッチ処理されません。
さいごに
公式に書かれている通り StrictMode で実装していればほぼゼロコストでマイグレーションが可能です。破壊的変更(過去のコードに影響する変更)はオプトインになり、 Automatic Batching などのあまり影響のない変更はデフォルトで有効になるそうです。
React18 のアップデートするだけでもパフォーマンス向上が見込めるので、まだ一般向けリリースまで数か月ありますがアップデートに向けて準備しておくのもいいかもしれません。
この記事を書いた人
- 創造性を最大限に発揮するとともに、インターネットに代表されるITを活用し、みんなの生活が便利で、豊かで、楽しいものになるようなサービスやコンテンツを考え、創り出し提供しています。
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー