Reactでページが真っ白|白い画面エラーの原因と対処法

Reactアプリで発生する白い画面エラーの原因と解決策を詳しく解説。JavaScriptエラー、ビルド問題、デプロイ設定の対処法を初心者向けに説明します。

Learning Next 運営
22 分で読めます

みなさん、Reactアプリで突然「真っ白な画面」が表示されて困ったことはありませんか?

「開発環境では動いていたのに、デプロイしたら真っ白...」 「昨日まで正常だったのに、なぜか白い画面になってしまった」 「どこから手をつけていいのか分からない」

こんな経験をしたことはありませんか?

この記事では、Reactアプリで発生する白い画面エラーの原因と、実際に使える解決方法を詳しく解説します。 焦らずに、一歩ずつ問題を解決していきましょう。

白い画面エラーって何?

Reactアプリの白い画面エラーは、実はとてもよくある問題なんです。

簡単に言うと、何らかの理由でReactコンポーネントが正常に表示されない状態のことです。 ブラウザには何も表示されず、真っ白な画面だけが見えてしまいます。

なぜ白い画面になるの?

通常、HTMLファイルには<div id="root"></div>という要素があります。 Reactはこの要素の中に、コンポーネントを表示します。

でも、何かのエラーでReactが動かなくなると、この要素は空のままになってしまいます。 結果として、白い画面が表示されるんです。

よくある場面

白い画面エラーは、こんな時によく起こります。

  • デプロイした後に急に表示されなくなった
  • 新機能を追加した後から白くなった
  • パッケージを更新した後に問題が発生
  • 環境を変更した時に動かなくなった

でも大丈夫です! 原因さえ分かれば、必ず解決できますよ。

原因を特定する最初の一歩

まずは、ブラウザの開発者ツールでエラーを確認しましょう。 これが問題解決の一番重要なステップです。

開発者ツールの開き方

Windows・Linux: F12キー
Mac: Command + Option + I

開発者ツールを開いたら、Console(コンソール)タブをクリックしてください。 ここにエラーメッセージが表示されています。

よく見るエラーメッセージ

こんなエラーメッセージが表示されることが多いです。

Uncaught TypeError: Cannot read property 'map' of undefined
Uncaught ReferenceError: Component is not defined
Uncaught SyntaxError: Unexpected token

エラーメッセージは怖く見えますが、実は問題を解決するヒントがたくさん含まれています。 まずはエラーメッセージをしっかり読んでみましょう。

Networkタブもチェック

Network(ネットワーク)タブも確認してみてください。 ファイルが正しく読み込まれているかチェックできます。

赤色で表示されているファイルがあれば、そのファイルが読み込めていません。 これも白い画面の原因になることがあります。

JavaScriptエラーで白い画面になる場合

一番よくある原因は、JavaScriptのエラーです。

データが存在しない問題

こんなコードを書いたことはありませんか?

// ❌ 問題のあるコード
const UserList = ({ users }) => {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

このコードの問題は、usersundefinedの時にエラーになることです。 undefined.map()は実行できないので、アプリが止まってしまいます。

// ✅ 修正後のコード
const UserList = ({ users }) => {
  // usersが存在しない場合の処理を追加
  if (!users || users.length === 0) {
    return <p>ユーザーがありません</p>;
  }

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

この修正により、データがない場合でも適切なメッセージが表示されます。

API呼び出しでのエラー

API呼び出しでもエラーが起こりやすいです。

// ❌ エラーハンドリングがない例
const fetchUserData = async () => {
  const response = await fetch('/api/users');
  const data = await response.json();
  setUsers(data);
};
// ✅ エラーハンドリングを追加
const fetchUserData = async () => {
  try {
    const response = await fetch('/api/users');
    
    if (!response.ok) {
      throw new Error('データの取得に失敗しました');
    }
    
    const data = await response.json();
    setUsers(data);
  } catch (error) {
    console.error('エラーが発生しました:', error);
    setError('データの読み込みに失敗しました');
  }
};

このようにtry-catchでエラーをキャッチすることで、エラーが発生してもアプリが停止しません。

Error Boundaryで安全に

Error Boundaryという仕組みを使うと、エラーが発生した時に適切なメッセージを表示できます。

// ErrorBoundary.js
import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, errorInfo) {
    console.error('エラーが発生しました:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div style={{ padding: '20px', textAlign: 'center' }}>
          <h2>🚨 エラーが発生しました</h2>
          <p>申し訳ございません。問題が発生しました。</p>
          <button onClick={() => window.location.reload()}>
            ページを再読み込み
          </button>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

このError Boundaryをアプリの最上位で使います。

// App.js
function App() {
  return (
    <ErrorBoundary>
      <div className="App">
        <Header />
        <MainContent />
        <Footer />
      </div>
    </ErrorBoundary>
  );
}

これで、どこかでエラーが発生しても、白い画面ではなく適切なエラーメッセージが表示されます。

ビルド設定で白い画面になる場合

開発環境では動くのに、ビルド後に白い画面になることもあります。

環境変数の設定を確認

環境変数の名前が間違っていると、ビルド時に問題が起こります。

# ❌ 間違った例
API_URL=https://api.example.com

# ✅ 正しい例(REACT_APP_で始める)
REACT_APP_API_URL=https://api.example.com
REACT_APP_VERSION=1.0.0

Reactでは、環境変数は必ずREACT_APP_で始める必要があります。 これを忘れると、ビルド時に環境変数が読み込まれません。

// 環境変数の使用例
const API_URL = process.env.REACT_APP_API_URL;

if (!API_URL) {
  console.error('API_URLが設定されていません');
}

package.jsonのhomepage設定

package.jsonhomepage設定も重要です。

{
  "name": "my-react-app",
  "version": "1.0.0",
  "homepage": "https://yourdomain.com",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test"
  }
}

デプロイ先のURLとhomepageの設定が合っていないと、ファイルが正しく読み込まれません。

ビルドエラーの確認方法

ビルド時にエラーが発生していないか確認しましょう。

# ビルドを実行
npm run build

# エラーが出ていないかチェック
# 成功すると "build" フォルダが作成される

# ローカルでビルド版をテスト
npx serve -s build

ビルドが成功すると、こんなメッセージが表示されます。

The build folder is ready to be deployed.

エラーメッセージが出た場合は、そのメッセージを読んで問題を解決しましょう。

パス設定で白い画面になる場合

ファイルのパス設定が間違っていると、必要なファイルが読み込まれません。

絶対パスと相対パス

パスの書き方には2つの方法があります。

// ❌ 相対パス(問題が起こりやすい)
import Header from './components/Header';
import './styles/App.css';

// ✅ 絶対パス(推奨)
import Header from 'components/Header';
import 'styles/App.css';

絶対パスを使うためには、srcフォルダにjsconfig.jsonを作成します。

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

これで、srcフォルダを基準とした絶対パスが使えるようになります。

React Routerの設定

React Routerを使っている場合、basenameの設定も重要です。

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Router basename="/your-app-name">
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </Router>
  );
}

サブディレクトリにデプロイする場合は、basenameにそのパスを指定してください。

public フォルダの画像パス

publicフォルダの画像は、こうやって参照します。

// ✅ public フォルダの画像
<img src="/logo.png" alt="ロゴ" />

// ✅ src フォルダの画像
import logo from './assets/logo.png';
<img src={logo} alt="ロゴ" />

間違ったパスを指定すると、画像が表示されずに問題の原因になることがあります。

デプロイ設定で白い画面になる場合

デプロイ先のサーバー設定が原因で白い画面になることもあります。

GitHub Pagesの設定

GitHub Pagesにデプロイする場合の設定例です。

// package.json
{
  "homepage": "https://yourusername.github.io/repository-name",
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  },
  "devDependencies": {
    "gh-pages": "^3.2.3"
  }
}

デプロイコマンドを実行します。

npm install --save-dev gh-pages
npm run deploy

Netlifyの設定

Netlifyの場合は、リダイレクト設定が必要です。

# netlify.toml
[build]
  publish = "build"
  command = "npm run build"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

この設定により、どのURLにアクセスしてもindex.htmlが返されます。 React Routerを使っている場合は、この設定が必須です。

Vercelの設定

Vercelの場合は、vercel.jsonを作成します。

{
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/index.html"
    }
  ]
}

Apacheサーバーの設定

Apacheサーバーの場合は、.htaccessファイルを作成します。

# .htaccess(buildフォルダに配置)
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

この設定により、存在しないファイルへのアクセスをindex.htmlにリダイレクトします。

実際のデバッグ手順

問題が発生した時の、具体的なデバッグ手順を説明します。

ステップ1: エラーメッセージを確認

まずは開発者ツールでエラーを確認します。

1. F12キーで開発者ツールを開く
2. Consoleタブでエラーメッセージを確認
3. Networkタブで読み込み失敗ファイルを確認
4. エラーメッセージをメモする

ステップ2: 最小限のコードで確認

問題を特定するため、最小限のコードから始めます。

// 最初はシンプルなコンポーネントから
function App() {
  return (
    <div>
      <h1>Hello World</h1>
    </div>
  );
}

export default App;

これが表示されるかチェックします。 表示されれば、徐々に機能を追加していきます。

ステップ3: 段階的に機能を追加

// 段階1: 基本的なコンポーネント
function App() {
  return (
    <div>
      <h1>Hello World</h1>
      <p>アプリが正常に動作しています</p>
    </div>
  );
}

// 段階2: 状態管理を追加
function App() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <h1>Hello World</h1>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        増加
      </button>
    </div>
  );
}

// 段階3: 他のコンポーネントを追加
function App() {
  return (
    <div>
      <Header />
      <Main />
      <Footer />
    </div>
  );
}

どの段階で問題が発生するか確認できます。

ステップ4: ログで動作確認

コンソールログを追加して、どこまで処理が進んでいるか確認します。

function App() {
  console.log('App component が読み込まれました');
  
  useEffect(() => {
    console.log('App component がマウントされました');
  }, []);

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

ログが表示されない場合は、コンポーネント自体に問題があります。

予防策でトラブルを避ける

白い画面エラーを予防する方法も知っておきましょう。

1. 型チェックを活用

PropTypesやTypeScriptを使って、型チェックを行います。

import PropTypes from 'prop-types';

const UserCard = ({ user }) => {
  return (
    <div>
      <h3>{user.name}</h3>
      <p>{user.email}</p>
    </div>
  );
};

UserCard.propTypes = {
  user: PropTypes.shape({
    name: PropTypes.string.isRequired,
    email: PropTypes.string.isRequired
  }).isRequired
};

型チェックにより、間違ったデータが渡された時にエラーで知らせてくれます。

2. デフォルト値を設定

const UserList = ({ users = [] }) => {
  return (
    <div>
      {users.length === 0 ? (
        <p>ユーザーがありません</p>
      ) : (
        <ul>
          {users.map(user => (
            <li key={user.id}>{user.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
};

デフォルト値を設定することで、データがない場合でも安全に動作します。

3. 定期的なビルドテスト

開発中も定期的にビルドテストを行います。

# 毎日のテストルーチン
npm run build
npx serve -s build

# ブラウザで http://localhost:3000 にアクセス
# 正常に表示されるかチェック

早めに問題を発見することで、対処が簡単になります。

4. エラーログの収集

本番環境では、エラーログを収集する仕組みを作っておきます。

// エラーログを送信する関数
const logError = (error, errorInfo) => {
  // ログ収集サービスに送信
  console.error('Error logged:', error, errorInfo);
};

class ErrorBoundary extends React.Component {
  componentDidCatch(error, errorInfo) {
    logError(error, errorInfo);
  }
  
  // ... その他のコード
}

ユーザーからエラー報告があった時に、すぐに原因を特定できます。

まとめ

Reactアプリの白い画面エラーについて、原因と対処法を詳しく解説しました。

主な原因と対処法

JavaScriptエラー: 条件分岐とError Boundaryで安全性を向上 ビルド設定: 環境変数とpackage.jsonの設定を確認 パス設定: 絶対パスの使用とReact Routerの適切な設定 デプロイ設定: サーバー側のリダイレクト設定を確認

デバッグの基本手順

  1. 開発者ツールでエラー確認
  2. 最小限のコードから段階的にテスト
  3. ログを追加して動作確認
  4. ビルドテストで本番環境をシミュレート

予防策

  • 型チェックでデータの整合性を確保
  • デフォルト値で安全性を向上
  • 定期的なビルドテストで早期発見
  • エラーログ収集で迅速な対応

白い画面エラーは最初は怖く感じるかもしれませんが、原因は必ずあります。 焦らずに一つずつ確認していけば、必ず解決できますよ。

大丈夫です! この記事の手順に従って、問題を解決していきましょう。

何度か経験すると、エラーの種類によって原因の予想がつくようになります。 ぜひ実際のプロジェクトで、これらの対処法を活用してみてください。

関連記事