Back to Biomejs

useComponentExportOnlyModules

src/content/docs/linter/rules/use-component-export-only-modules.mdx

latest8.3 KB
Original Source

import { Tabs, TabItem } from '@astrojs/starlight/components';

<Tabs> <TabItem label="JSX and TSX" icon="seti:javascript"> ## Summary - Rule available since: `v1.9.2` - Diagnostic Category: [`lint/style/useComponentExportOnlyModules`](/reference/diagnostics#diagnostic-category) - This rule isn't recommended, so you need to enable it. - This rule doesn't have a fix. - The default severity of this rule is [**warning**](/reference/diagnostics#warning). - This rule belongs to the following domains: - [`react`](/linter/domains#react) - Sources: - Inspired from [`react-refresh/only-export-components`](https://github.com/ArnaudBarre/eslint-plugin-react-refresh)

How to configure

json
{
	"linter": {
		"rules": {
			"style": {
				"useComponentExportOnlyModules": "error"
			}
		}
	}
}

Description

Enforce declaring components only within modules that export React Components exclusively.

This is necessary to enable the React Fast Refresh feature, which improves development efficiency. The determination of whether something is a component depends on naming conventions. Components should be written in PascalCase and regular functions in camelCase. If the framework already has established conventions, consider optionally specifying exceptions.

Examples

Invalid

jsx
export const foo = () => {};
export const Bar = () => <></>;
<pre class="language-text"><code class="language-text">code-block.jsx:1:14 <a href="https://biomejs.dev/linter/rules/use-component-export-only-modules">lint/style/useComponentExportOnlyModules</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: Orange;">⚠</span></strong> <span style="color: Orange;">Exporting a non-component with components is not allowed.</span> <strong><span style="color: Tomato;">&gt;</span></strong> <strong>1 │ </strong>export const foo = () =&gt; &#123;&#125;; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>2 │ </strong>export const Bar = () =&gt; &lt;&gt;&lt;/&gt;; <strong>3 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;"><a href="https://github.com/facebook/react/tree/main/packages/react-refresh">Fast Refresh</a></span><span style="color: lightgreen;"> only works when a file only exports components.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Consider separating non-component exports into a new file.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">If it is a component, it may not be following the variable naming conventions.</span> </code></pre>
jsx
const Tab = () => {};
export const tabs = [<Tab />, <Tab />];
<pre class="language-text"><code class="language-text">code-block.jsx:1:7 <a href="https://biomejs.dev/linter/rules/use-component-export-only-modules">lint/style/useComponentExportOnlyModules</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: Orange;">⚠</span></strong> <span style="color: Orange;">Components should be exported.</span> <strong><span style="color: Tomato;">&gt;</span></strong> <strong>1 │ </strong>const Tab = () =&gt; &#123;&#125;; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>2 │ </strong>export const tabs = [&lt;Tab /&gt;, &lt;Tab /&gt;]; <strong>3 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;"><a href="https://github.com/facebook/react/tree/main/packages/react-refresh">Fast Refresh</a></span><span style="color: lightgreen;"> only works when a file only exports components.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Consider separating component exports into a new file.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">If it is not a component, it may not be following the variable naming conventions.</span> </code></pre>
jsx
const App = () => {}
createRoot(document.getElementById("root")).render(<App />);
<pre class="language-text"><code class="language-text">code-block.jsx:1:7 <a href="https://biomejs.dev/linter/rules/use-component-export-only-modules">lint/style/useComponentExportOnlyModules</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: Orange;">⚠</span></strong> <span style="color: Orange;">Unexported components are not allowed.</span> <strong><span style="color: Tomato;">&gt;</span></strong> <strong>1 │ </strong>const App = () =&gt; &#123;&#125; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>2 │ </strong>createRoot(document.getElementById(&quot;root&quot;)).render(&lt;App /&gt;); <strong>3 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;"><a href="https://github.com/facebook/react/tree/main/packages/react-refresh">Fast Refresh</a></span><span style="color: lightgreen;"> only works when a file only exports components.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Consider separating component exports into a new file.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">If it is not a component, it may not be following the variable naming conventions.</span> </code></pre>

Valid

jsx
export default function Foo() {
    return <></>;
}
jsx
const foo = () => {};
export const Bar = () => <></>;
jsx
import { App } from "./App";
createRoot(document.getElementById("root")).render(<App />);

Functions that return standard React components are also permitted.

jsx
import { memo } from 'react';
const Component = () => <></>
export default memo(Component);

Options

allowConstantExport

Some tools, such as Vite, allow exporting constants along with components. By enabling the following, the rule will support the pattern.

json
{
	"linter": {
		"rules": {
			"style": {
				"useComponentExportOnlyModules": {
					"options": {
						"allowConstantExport": true
					}
				}
			}
		}
	}
}

allowExportNames

If you use a framework that handles Hot Module Replacement(HMR) of some specific exports, you can use this option to avoid warning for them.

Example for Remix:

json
{
	"linter": {
		"rules": {
			"style": {
				"useComponentExportOnlyModules": {
					"options": {
						"allowExportNames": [
							"json",
							"loader",
							"headers",
							"meta",
							"links",
							"scripts"
						]
					}
				}
			}
		}
	}
}

</TabItem> </Tabs>