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 &&