logo Ribbit's works

【React】レンダリング終了を待って処理する

#JavaScript #React
にメンテナンス済み
記事のトップ画像

⚠️ 重要な更新情報

React 18以降、ReactDOM.renderは非推奨となりました。 この記事の内容は主にReact 17以前の情報です。

React 18ではcreateRoot APIが推奨され、レンダリング後のコールバック機能は削除されています。

React 17以前の情報(Legacy)

結論(React 17まで)

ReactDOM.render(element, container[, callback])

オプションのコールバックが渡されている場合は、コンポーネントがレンダーまたは更新された後に実行されます。

ReactDOM - React(Legacy)

React 17での実装例

import React from 'react';
import { render } from 'react-dom';

render(<div></div>, document.body, onRenderingFinish);

console.log('renderの後ろの処理');

function onRenderingFinish() {
  console.log('renderのコールバック処理');
}

React 18以降の実装方法

React 18では以下の方法でレンダリング後の処理を実行します:

1. ref callbackを使用する方法

import { createRoot } from 'react-dom/client';
import React from 'react';

function App({ callback }) {
  // callbackはdivが作成されたときに実行されます
  return (
    <div ref={callback}>
      <h1>Hello World</h1>
    </div>
  );
}

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App callback={() => console.log('レンダリング完了')} />);

2. useEffectを使用する方法

import { createRoot } from 'react-dom/client';
import React, { useEffect } from 'react';

function App() {
  useEffect(() => {
    console.log('コンポーネントがマウントされました');
  }, []);

  return (
    <div>
      <h1>Hello World</h1>
    </div>
  );
}

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);

3. flushSyncを使用する方法(同期的な更新が必要な場合)

import { createRoot } from 'react-dom/client';
import { flushSync } from 'react-dom';
import React, { useState } from 'react';

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    // flushSyncを使用して同期的に更新
    flushSync(() => {
      setCount(c => c + 1);
    });
    // この時点でDOMは既に更新されています
    console.log('更新完了:', count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>更新</button>
    </div>
  );
}

環境情報

Legacy環境(React 17)

node.js14.15.0
npm6.14.9
React17.x

現在推奨の環境(React 18+)

React18.0.0+
Node.js16.0.0+

まとめ

  • React 17まで: ReactDOM.renderの第3引数でコールバックを指定可能
  • React 18以降: createRootを使用し、ref callbackやuseEffectでレンダリング後の処理を実装
  • 同期的な更新が必要な場合はflushSyncを検討

React 18への移行時は、公式マイグレーションガイドを参照することを推奨します。

実行結果(React 17)

renderの後ろの処理
renderのコールバック処理

この結果からわかるように、React 17ではrender関数が即座に戻り、その後にコールバック関数が実行されました。

注意: この動作はReact 18では使用できないため、上記の新しい方法を使用してください。