Description
When allowConstantExport: true is set, react/only-export-components permits all export const declarations without checking whether the exported value is actually a React component.
eslint-plugin-react-refresh correctly checks whether the value is a component and reports an error when it is not.
Reproduction
https://github.com/eai04191/oxlint-only-export-components-repro
git clone https://github.com/eai04191/oxlint-only-export-components-repro
cd oxlint-only-export-components-repro
npm ci
# oxlint: no error (bug)
npx oxlint -c oxlint.config.json should-error.tsx
# eslint: reports error (correct)
npx eslint -c eslint.config.mjs should-error.tsx
The repo also has a CI workflow that demonstrates the difference.
should-error.tsx
function createFileRoute(_path: string) {
return (_opts: Record<string, unknown>) => ({ _path });
}
export const Route = createFileRoute("/example")({
component: RouteComponent,
});
function RouteComponent() {
return <div>Hello</div>;
}
Config
{
"plugins": ["react"],
"rules": {
"react/only-export-components": ["error", { "allowConstantExport": true }]
}
}
Expected
should-error.tsx should report an error because export const Route = createFileRoute(...)({...}) is not a React component — it's a function call returning a plain object.
Actual
No error reported. allowConstantExport: true permits all export const regardless of whether the value is a component.
Context
This matters for TanStack Router file-based routing. createFileRoute() returns a Route object, not a React component. When a component is colocated in the same file, changes to non-component properties (like loader) won't trigger HMR correctly. The lint rule should warn about this.
eslint-plugin-react-refresh added detection for this pattern in v0.5.0:
https://github.com/ArnaudBarre/eslint-plugin-react-refresh/releases/tag/v0.5.0
Versions
- oxlint: 1.56.0
- eslint-plugin-react-refresh: 0.5.2
Description
When
allowConstantExport: trueis set,react/only-export-componentspermits allexport constdeclarations without checking whether the exported value is actually a React component.eslint-plugin-react-refreshcorrectly checks whether the value is a component and reports an error when it is not.Reproduction
https://github.com/eai04191/oxlint-only-export-components-repro
The repo also has a CI workflow that demonstrates the difference.
should-error.tsxConfig
{ "plugins": ["react"], "rules": { "react/only-export-components": ["error", { "allowConstantExport": true }] } }Expected
should-error.tsxshould report an error becauseexport const Route = createFileRoute(...)({...})is not a React component — it's a function call returning a plain object.Actual
No error reported.
allowConstantExport: truepermits allexport constregardless of whether the value is a component.Context
This matters for TanStack Router file-based routing.
createFileRoute()returns a Route object, not a React component. When a component is colocated in the same file, changes to non-component properties (likeloader) won't trigger HMR correctly. The lint rule should warn about this.eslint-plugin-react-refreshadded detection for this pattern in v0.5.0:https://github.com/ArnaudBarre/eslint-plugin-react-refresh/releases/tag/v0.5.0
Versions