diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2bdcebc..18350f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,8 @@
# Changelog
-## Unreleased
+## 0.4.4
+- Add `allowExportNames` option (fixes #29)
- Support memo default export function components (fixes #27)
- Warn on export expressions that are not React component (array, object, logical expression, ...) (fixes #26)
diff --git a/README.md b/README.md
index 1b976b0..6a8180c 100644
--- a/README.md
+++ b/README.md
@@ -83,6 +83,21 @@ createRoot(document.getElementById("root")).render();
## Options
+### allowExportNames (v0.4.4)
+
+If you use a framework that handles HMR of some specific exports, you can use this option to avoid warning for them.
+
+Example for [Remix](https://remix.run/docs/en/main/other-api/dev#:~:text=React%20Fast%20Refresh,-can%20only%20handle):
+
+```json
+{
+ "react-refresh/only-export-components": [
+ "warn",
+ { "allowExportNames": ["meta", "links", "headers", "loader", "action"] }
+ ]
+}
+```
+
### allowConstantExport (v0.4.0)
Don't warn when a constant (string, number, boolean, templateLiteral) is exported aside one or more components.
diff --git a/package.json b/package.json
index ea66993..78d680b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-react-refresh",
- "version": "0.4.3",
+ "version": "0.4.4",
"license": "MIT",
"scripts": {
"build": "scripts/bundle.ts",
diff --git a/src/only-export-components.test.ts b/src/only-export-components.test.ts
index 4d2a3e5..78c1f57 100755
--- a/src/only-export-components.test.ts
+++ b/src/only-export-components.test.ts
@@ -116,6 +116,21 @@ const valid = [
code: "const foo = 'world'; export const CONSTANT = `Hello ${foo}`; export const Foo = () => {};",
options: [{ allowConstantExport: true }],
},
+ {
+ name: "Component and allowed export",
+ code: "export const loader = () => {}; export const Bar = () => {};",
+ options: [{ allowExportNames: ["loader", "meta"] }],
+ },
+ {
+ name: "Component and allowed function export",
+ code: "export function loader() {}; export const Bar = () => {};",
+ options: [{ allowExportNames: ["loader", "meta"] }],
+ },
+ {
+ name: "Only allowed exports without component",
+ code: "export const loader = () => {}; export const meta = { title: 'Home' };",
+ options: [{ allowExportNames: ["loader", "meta"] }],
+ },
];
const invalid = [
@@ -201,6 +216,12 @@ const invalid = [
filename: "Test.jsx",
errorId: "anonymousExport",
},
+ {
+ name: "Component and export non in allowExportNames",
+ code: "export const loader = () => {}; export const Bar = () => {}; export const foo = () => {};",
+ options: [{ allowExportNames: ["loader", "meta"] }],
+ errorId: "namedExport",
+ },
];
const it = (name: string, cases: Parameters[2]) => {
diff --git a/src/only-export-components.ts b/src/only-export-components.ts
index 0fcda7c..c423b6d 100644
--- a/src/only-export-components.ts
+++ b/src/only-export-components.ts
@@ -14,7 +14,14 @@ export const onlyExportComponents: TSESLint.RuleModule<
| "anonymousExport"
| "noExport"
| "localComponents",
- [] | [{ allowConstantExport?: boolean; checkJS?: boolean }]
+ | []
+ | [
+ {
+ allowConstantExport?: boolean;
+ checkJS?: boolean;
+ allowExportNames?: string[];
+ },
+ ]
> = {
meta: {
messages: {
@@ -36,6 +43,7 @@ export const onlyExportComponents: TSESLint.RuleModule<
properties: {
allowConstantExport: { type: "boolean" },
checkJS: { type: "boolean" },
+ allowExportNames: { type: "array", items: { type: "string" } },
},
additionalProperties: false,
},
@@ -43,8 +51,11 @@ export const onlyExportComponents: TSESLint.RuleModule<
},
defaultOptions: [],
create: (context) => {
- const { allowConstantExport = false, checkJS = false } =
- context.options[0] || {};
+ const {
+ allowConstantExport = false,
+ checkJS = false,
+ allowExportNames,
+ } = context.options[0] || {};
const filename = context.getFilename();
// Skip tests & stories files
if (
@@ -86,6 +97,9 @@ export const onlyExportComponents: TSESLint.RuleModule<
nonComponentExports.push(identifierNode);
return;
}
+ if (allowExportNames?.includes(identifierNode.name)) {
+ return;
+ }
if (
allowConstantExport &&
init &&