React

【Vite】Fast refresh only works when a file only exports components.エラーが出た!

更新日:2026/02/16

ViteでESLintが次の警告を出しているのに気が付きました。

Fast refresh only works when a file only exports components.

なんだこれと思いながら対処したというお話です。

 

エラーの内容

コードが数行のみのエクスポートファイルを削除して、内容をコンポーネントファイルに移動したら、次のエラーがでました。

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.eslint(react-refresh/only-export-components)

『高速リフレッシュは ”コンポーネントだけを export しているファイル” でしか正しく動きません。だから定数や関数を共有したいなら、別ファイルに分けてください。』

という意味ですね。

次のようにコンポーネントのみのエクスポートはエラーになりません。

OKパターン

function App1(){
  return <p>text1</p>
}
function App2() {
  return <p>text2</p>
}
export { App1,App2};

しかし、次のようにコンポーネント以外のデータをエクスポートするとエラーになります。

NGパターン

function getText(){
  return "text1";
}
function App2() {
  return <p>text2</p>
}
export { App2,getText};

ただし、コンポーネントかどうかの判定は、何を返しているかではなくて関数名が大文字で開始しているかどうかのようです。

コンポーネントしかエクスポートしていないのにエラーが出る、というときは開始文字を確認しましょう。

 

対処法

まずは対処法から。
高速リフレッシュについては、次項で紹介します。

エラーが出た時の対処法は三つです。

ファイルを分ける

コンポーネントのみをエクスポートしているファイルと、その他のデータをエクスポートしているファイルに分けます。

この方法が一番安全ですね。

せっかく一つのファイルにまとめましたが、最初は何らかの意図があって別ファイルにしていたので元に戻すことにしました。

そのまま使う

高速リフレッシュが有効でない場合は、ブラウザの再読み込みを行えばデバッグ可能です。
そのため、小規模なプロジェクトなら高速リフレッシュの恩恵が少ないかもしれません。

時々再起動を忘れて動作が不安定になる可能性がありますが、ファイル数を増やしたくない場合はこの方法を使用しましょう。

ESLint側で無効にする

個人的には非推奨ですが、ファイルに次のコメントを記述すると、高速リフレッシュに関するエラー出力をファイル単位で抑制できます。

/* eslint-disable react-refresh/only-export-components */

または、次のコメントで後に続く行のエラー出力を抑制できます。

// eslint-disable-next-line react-refresh/only-export-components

上述の二つのコメントは、今回のエラーの他に次のエラーも抑制対象となります。

「This rule can't verify that `export *` only exports components.」
意訳:export * を使用してはいけません。

「Fast refresh can't handle anonymous components. Add a name to your export.」
意訳:コンポーネントに名前を付けないでエクスポートしてはいけません。

「Fast refresh only works when a file only exports components. Move your component(s) to a separate file.」
意訳:コンポーネント以外のデータがエクスポートされています。コンポーネントを別ファイルに移動してください。

「Fast refresh only works when a file has exports. Move your component(s) to a separate file.」
意訳:コンポーネントファイルなのにエクスポートがありません。

「Fast refresh only works when a file only exports components. Move your React context(s) to a separate file.」
意訳:Reactコンテキストを別のファイルに移動してください。

 

高速リフレッシュとは

高速リフレッシュ(Fast Refresh)とは、Reactコードの変更をブラウザに反映させる仕組みです。
ブラウザを再読み込みする必要がないため、開発効率を上げることができます。

モジュール単位でコードを置き換える技術をHMR(Hot Module Replacement)と呼びます。
高速リフレッシュはReact版のHMRのようですね。

高速リフレッシュはファイルがReactのコンポーネントかどうかを判断して、コンポーネントのときstateを保持したままコードを更新します。
しかしコンポーネント以外のデータがエクスポートされていると、コンポーネントかどうかの判断ができないため高速リフレッシュが無効になります。

そのため、今回のエラーが検出されたのです。

 

Viteでの高速リフレッシュ設定

Viteをテンプレートからインストールすると作成されるREADME.mdを見ると、次のような記述がありました。

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

日本語訳:

現在、2つの公式プラグインが利用可能です。

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) は、高速リフレッシュのために [Babel](https://babeljs.io/) (または [rolldown-vite](https://vite.dev/guide/rolldown) で使用される場合は [oxc](https://oxc.rs))を使用します。
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) は、高速リフレッシュのために [SWC](https://swc.rs/) を使用します。

ViteでReactの高速リフレッシュを有効にするために、@vitejs/plugin-reactプラグインまたは@vitejs/plugin-react-swcプラグインが必要のようです。
これらはViteのテンプレートを使ってReactをインストールすると自動でインストールされ、vite.config.jsで読み込まれます。

 

ESLint側の設定

今回のエラーはESLintが出力しています。
そこで、ESLint側の設定を確認してみます。

設定ファイルのeslint.config.jsは、Viteのテンプレートが自動生成したものです。

eslint.config.js

import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{js,jsx}'],
    extends: [
      js.configs.recommended,
      reactHooks.configs.flat.recommended,
      reactRefresh.configs.vite,
    ],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
      parserOptions: {
        ecmaVersion: 'latest',
        ecmaFeatures: { jsx: true },
        sourceType: 'module',
      },
    },
    rules: {
      'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
    },
  },
])

ここでは幾つかのファイルをインポートしています。
この中でeslint-plugin-react-refreshが高速リフレッシュに関連していそうなので、このプラグインの解説ページを確認してみます。

コンポーネントが Fast Refresh で安全に更新できることを検証します。
https://www.npmjs.com/package/eslint-plugin-react-refresh

eslint-plugin-react-refreshのインポート先はreactRefreshオブジェクトですね。
そしてreactRefresh.configs.viteがプラグインとして読み込まれています。

更新日:2026/02/16

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。