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); · ───────────