From cee29b4cf8e23e64e8329fbe10af154e9e172e7d Mon Sep 17 00:00:00 2001
From: connorshea <2977353+connorshea@users.noreply.github.com>
Date: Fri, 23 Jan 2026 14:44:47 +0000
Subject: [PATCH] fix(linter): Remove confusing scope from
`react/only-export-components` rule diagnostics. (#18434)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
And also credits the original rule source in the docs.
Previously, the diagnostics looked like this, which lead to confusion about the rule's name/plugin/scope, and how to disable it in the config file:
```
⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:14]
1 │ export const foo = () => {}; export const Bar = () => {};
· ───
╰────
```
Now they look like this:
```
⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:14]
1 │ export const foo = () => {}; export const Bar = () => {};
· ───
╰────
```
Technically this means that the diagnostic message will now say it's from eslint-plugin-react, but that's fine and should be less confusing for the end-user.
Resolves #18070.
---
.../src/rules/react/only_export_components.rs | 10 +----
.../react_only_export_components.snap | 42 +++++++++----------
2 files changed, 23 insertions(+), 29 deletions(-)
diff --git a/crates/oxc_linter/src/rules/react/only_export_components.rs b/crates/oxc_linter/src/rules/react/only_export_components.rs
index 8dc159f176b8e..3e223f9c8b828 100644
--- a/crates/oxc_linter/src/rules/react/only_export_components.rs
+++ b/crates/oxc_linter/src/rules/react/only_export_components.rs
@@ -12,18 +12,14 @@ use crate::{
rule::{DefaultRuleConfig, Rule},
};
-const SCOPE: &str = "eslint-plugin-react-refresh";
-
fn export_all_components_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("This rule can't verify that `export *` only exports components.")
.with_label(span)
- .with_error_code_scope(SCOPE)
}
fn named_export_components_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.")
.with_label(span)
- .with_error_code_scope(SCOPE)
}
fn anonymous_components_diagnostic(span: Span) -> OxcDiagnostic {
@@ -31,25 +27,21 @@ fn anonymous_components_diagnostic(span: Span) -> OxcDiagnostic {
"Fast refresh can't handle anonymous components. Add a name to your export.",
)
.with_label(span)
- .with_error_code_scope(SCOPE)
}
fn local_components_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Fast refresh only works when a file only exports components. Move your component(s) to a separate file.")
.with_label(span)
- .with_error_code_scope(SCOPE)
}
fn no_export_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Fast refresh only works when a file has exports. Move your component(s) to a separate file.")
.with_label(span)
- .with_error_code_scope(SCOPE)
}
fn react_context_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Fast refresh only works when a file only exports components. Move your React context(s) to a separate file.")
.with_label(span)
- .with_error_code_scope(SCOPE)
}
#[derive(Debug, Default, Clone, Deserialize)]
@@ -100,6 +92,8 @@ declare_oxc_lint!(
/// (e.g. `createRoot(...).render()`) to match what integrations like
/// `react-refresh` expect.
///
+ /// This rule is based on the rule from `eslint-plugin-react-refresh`.
+ ///
/// ### Why is this bad?
///
/// Fast Refresh can only reliably retain state if a module exports components and
diff --git a/crates/oxc_linter/src/snapshots/react_only_export_components.snap b/crates/oxc_linter/src/snapshots/react_only_export_components.snap
index 5244130a3bea0..b81be99dfbdd6 100644
--- a/crates/oxc_linter/src/snapshots/react_only_export_components.snap
+++ b/crates/oxc_linter/src/snapshots/react_only_export_components.snap
@@ -1,85 +1,85 @@
---
source: crates/oxc_linter/src/tester.rs
---
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:14]
1 │ export const foo = () => {}; export const Bar = () => {};
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:14]
1 │ export const foo = () => {}; export const Bar = () => {};
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:14]
1 │ export const foo = 4; export const Bar = () => {};
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:46]
1 │ export function Component() {}; export const Aa = 'a'
· ──
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:47]
1 │ const foo = 4; const Bar = () => {}; export { foo, Bar };
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): This rule can't verify that `export *` only exports components.
+ ⚠ eslint-plugin-react(only-export-components): This rule can't verify that `export *` only exports components.
╭─[only_export_components.tsx:1:1]
1 │ export * from './foo';
· ──────────────────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
╭─[only_export_components.tsx:1:1]
1 │ export default () => {};
· ────────────────────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
╭─[only_export_components.tsx:1:1]
1 │ export default memo(() => {});
· ──────────────────────────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
╭─[only_export_components.tsx:1:16]
1 │ export default function () {};
· ──────────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:14]
1 │ export const CONSTANT = 3; export const Foo = () => {};
· ────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:13]
1 │ export enum Tab { Home, Settings }; export const Bar = () => {};
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Move your component(s) to a separate file.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Move your component(s) to a separate file.
╭─[only_export_components.tsx:1:7]
1 │ const Tab = () => {}; export const tabs = [, ];
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file has exports. Move your component(s) to a separate file.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file has exports. Move your component(s) to a separate file.
╭─[only_export_components.tsx:1:7]
1 │ const App = () => {}; createRoot(document.getElementById('root')).render();
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:3:22]
2 │ import React from 'react';
3 │ export const CONSTANT = 3; export const Foo = () => {};
@@ -87,43 +87,43 @@ source: crates/oxc_linter/src/tester.rs
4 │
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
╭─[only_export_components.tsx:1:1]
1 │ export default compose()(MainView);
· ───────────────────────────────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.
╭─[only_export_components.tsx:1:75]
1 │ export const loader = () => {}; export const Bar = () => {}; export const foo = () => {};
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Move your component(s) to a separate file.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Move your component(s) to a separate file.
╭─[only_export_components.tsx:1:7]
1 │ const Foo = () => {}; export { Foo as "🍌"}
· ───
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Move your React context(s) to a separate file.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Move your React context(s) to a separate file.
╭─[only_export_components.tsx:1:51]
1 │ export const MyComponent = () => {}; export const MyContext = createContext('test');
· ─────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Move your React context(s) to a separate file.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Move your React context(s) to a separate file.
╭─[only_export_components.tsx:1:51]
1 │ export const MyComponent = () => {}; export const MyContext = React.createContext('test');
· ─────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh can't handle anonymous components. Add a name to your export.
╭─[only_export_components.tsx:1:31]
1 │ const MyComponent = () => {}; export default observer(MyComponent);
· ─────────────────────────────────────
╰────
- ⚠ eslint-plugin-react-refresh(only-export-components): Fast refresh only works when a file only exports components. Move your component(s) to a separate file.
+ ⚠ eslint-plugin-react(only-export-components): Fast refresh only works when a file only exports components. Move your component(s) to a separate file.
╭─[only_export_components.tsx:1:7]
1 │ const MyComponent = () => {}; export default observer(MyComponent);
· ───────────