Skip to content

linter: react/only-export-components with allowConstantExport does not detect non-component export const #20455

Description

@eai04191

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions