Reactバージョンアップの影響調査と移行支援

Reactバージョンアップの影響調査と移行支援
2024/07/01に公開

はじめに

本記事では、Reactのメジャーバージョンアップにおける互換性調査・技術支援の実例を紹介します。

今回ご依頼いただいたのは、Web制作会社様の開発案件です。特殊な機能をReact 16で実装していたものの、開発メンバーの離脱により保守が難航。エンドユーザーから新機能の追加要望が出た一方で、必要なライブラリが現在のReactバージョンと互換性がなく、技術的な足止めが発生していました。

このような状況は、リソース制約のある開発チームや保守フェーズに入ったシステムでよく見られる構造です。本記事では、Reactのバージョンを16から18に安全にアップグレードし、継続可能な運用体制を整えるまでの支援内容を紹介します。

支援の進め方

影響調査と方針設計

  • React 16 → 17 → 18 の2段階で段階的にアップグレード
  • 公式リリースノートをもとに、破壊的変更・非推奨機能・新機能を整理
  • 特にクラスコンポーネントのレガシーAPIやライフサイクルメソッドの使用箇所を洗い出し、関数コンポーネント + useEffect への移行を検討

Image from Gyazo

参考: React公式リリースノート

影響調査の具体例

  • componentWillMountuseEffect に書き換え
    • React 17以降では componentWillMount は完全に廃止され、警告も出るようになっているため。
    • クラスベースの初期化処理は、関数コンポーネントでの useEffect に移行することで、モダンな構成に対応可能。
// Before
class Example extends React.Component {
  componentWillMount() {
    this.setState({ ready: true })
  }
  render() {
    return <div>...</div>
  }
}

// After
const Example = () => {
  const [ready, setReady] = useState(false)
  useEffect(() => {
    setReady(true)
  }, [])
  return <div>...</div>
}
  • ReactDOM.render の変更: ReactDOM.createRoot を用いた新しいレンダリング方法に対応しました。

依存関係の整理

  • Webpack: v4 → v5 へアップグレード(依存loaderも更新)
  • Jest: 最新バージョンに更新、setupFilesAfterEnvなど設定も移行
    • Jest v27以降での設定方式が変更されたため。以前のsetupFilesでは動作しないケースがあり、移行が必要。
    • 具体的には、旧来の setupFiles を削除し、以下のように jest.config.js を更新:
// Before
module.exports = {
  setupFiles: ['<rootDir>/jest.setup.js'],
}

// After
module.exports = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
}
  • React Testing Library: API仕様の変更に合わせてテストコードを修正
    • React 18対応に伴い waitFor, findBy* 系のAPIの挙動が変化し、一部の非同期テストで修正が必要になったため。
    • 例:await wait() の廃止に伴い、waitFor() に書き換え
// Before
await wait(() => {
  expect(screen.getByText('完了')).toBeInTheDocument()
})

// After
await waitFor(() => {
  expect(screen.getByText('完了')).toBeInTheDocument()
})
  • バージョン競合が起きないよう、package-lock.json を削除し、ロックファイルを再生成。
  • 以下のように対応
    • rm -rf node_modules package-lock.json
    • npm installを実行
    • npm dedupe などで依存の重複整理も実施

3. シナリオテスト(E2Eテスト)の導入

バージョンアップ後の動作検証として、Playwright を用いたE2Eテストを事前に実装しました。

  • 2段階バージョンアップに備え、各段階でテストを実施
  • 今後の定期的なバージョンアップも考慮し、自動テスト環境を構築

技術的な工夫・コード例

React 18移行時のエントリーポイント修正

React 18では ReactDOM.render() が非推奨になったため、新しい createRoot() API を使用しています。

index.tsx
import { createRoot } from 'react-dom/client'
import App from './App'

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

act() 警告への対応(React 18 + テスト環境)

React 18以降では、テスト実行中に副作用がある処理(useEffectなど)をテストで扱う際に act() を使っていないと、警告が出るようになりました。

多くのテストランナー(Jestなど)やライブラリ(React Testing Libraryなど)は内部で act() を自動的にラップしてくれているのですが、それをReact側が正しく認識するために、次のような“おまじない”が必要になります:

jest.setup.ts
globalThis.IS_REACT_ACT_ENVIRONMENT = true

これがあることで、Reactは「これはテスト環境ですよ」と理解し、自動的にactされている前提で動いてくれます。

StrictModeによる二重レンダリングとconsole警告の制御

React 18ではStrictModeが useEffect を2回呼ぶ動作があり、開発・テスト中にログが増えすぎることへの対策も実施しました

App.tsx
<React.StrictMode>
  <App />
</React.StrictMode>
jest.setup.ts
beforeAll(() => {
  jest.spyOn(console, 'error').mockImplementation((...args) => {
    const [msg] = args
    if (
      typeof msg === 'string' &&
      msg.includes('Warning: useEffect has been called multiple times')
    ) {
      return
    }
    console.error(...args)
  })
})

バージョンアップによるメリット

セキュリティリスクの低減

  • Reactと関連ライブラリを最新化したことで、既知の脆弱性が解消され、セキュリティの強化につながりました。

ビルド時間の短縮

  • Webpackビルド時間が約20〜30%短縮
  • 最新のESM対応や最適化オプションの利用が可能に

システム監視の強化

  • E2Eテストが外形監視の役割を果たし、障害検知・復旧の初動が迅速に
  • リグレッションの予防ができる体制が整備された

今後の展開

今回のReactバージョンアップ対応により、技術的な負債の解消と開発基盤のモダン化が一段落しました。今後は以下のような展開を見据えています:

  • 定期的な依存ライブラリのバージョン監視と更新

    • RenovateやDependabotの導入により、ライブラリの脆弱性・破壊的変更を早期に検出し対応する体制を整備予定
  • より実運用に近い自動テストの充実

    • PlaywrightによるE2Eテストをベースに、操作ログの再現やブラウザ依存の検証なども強化し、サービス品質の維持に貢献
  • TypeScriptの型定義・保守性向上に向けた型の厳格化

    • anyや緩い型定義を見直し、エラーの早期検出と安全な開発を推進
  • エラー監視・パフォーマンス監視の導入検討

    • SentryやLighthouse CIなどと連携し、ユーザー体験の継続的な観測と改善を目指す
  • React 17/18で追加された新機能の段階的導入

    • startTransitionuseId, useDeferredValue, useSyncExternalStore など、ユーザー体験や描画制御に関わるAPIを今後の改修の中で導入検討
    • パフォーマンスチューニングや状態管理改善に向けた活用を想定

まとめ

本支援では、React 16 → 18への段階的アップグレードを、影響調査・依存整理・テスト基盤整備を通じて安全に実現しました。

特に、保守フェーズにあるプロジェクトやリソースに制限のある現場においては、今回のような「段階移行」「テストでの裏付け」「運用しやすさの確保」が極めて重要です。

今後も、Reactをはじめとするライブラリの継続的な更新に対応できる体制づくりを、技術面・体制面の両側面から支援してまいります。

Xでシェア
Facebookでシェア
LinkedInでシェア

関連する技術ブログ

お問い合わせ

開発・セキュリティ・品質を包括的に見直し、
持続可能なプロダクト開発をサポートします。

お問い合わせ