diff --git a/README.md b/README.md index ea4e0ec..d45dc99 100644 --- a/README.md +++ b/README.md @@ -140,3 +140,22 @@ If your using JSX inside `.js` files (which I don't recommend because it forces "react-refresh/only-export-components": ["warn", { "checkJS": true }] } ``` + +### createContextMethods + +The `createContextMethods` option allows you to specify custom context-creating functions for detection by the rule. By default, it only detects `createContext`, but you can add methods like `createMyContext` in your configuration. + +```json +{ + "react-refresh/only-export-components": [ + "error", + { "createContextMethods": ["createMyContext"] } + ] +} +``` + +```jsx +export const MyComponent = () =>
; +// ESLint error +export const MyContext = createMyContext(); +``` diff --git a/src/only-export-components.test.ts b/src/only-export-components.test.ts index b5accd9..fd42deb 100755 --- a/src/only-export-components.test.ts +++ b/src/only-export-components.test.ts @@ -189,6 +189,10 @@ const valid = [ name: "Only React context", code: "export const MyContext = createContext('test');", }, + { + name: "Component and React Context from other module without options", + code: "export const MyComponent = () => {}; export const MyContext = createMyContext('test');", + }, ]; const invalid = [ @@ -295,6 +299,14 @@ const invalid = [ code: "export const MyComponent = () => {}; export const MyContext = React.createContext('test');", errorId: "reactContext", }, + { + name: "Component and React Context from other module", + code: "export const MyComponent = () => {}; export const MyContext = createMyContext('test');", + errorId: "reactContext", + options: [ + { createContextMethods: ["createMyContext"] }, + ], + }, ]; const it = (name: string, cases: Parameters[2]) => { diff --git a/src/only-export-components.ts b/src/only-export-components.ts index b74a285..b37b527 100644 --- a/src/only-export-components.ts +++ b/src/only-export-components.ts @@ -21,6 +21,7 @@ export const onlyExportComponents: TSESLint.RuleModule< allowConstantExport?: boolean; checkJS?: boolean; allowExportNames?: string[]; + createContextMethods?: string[]; }, ] > = { @@ -47,6 +48,7 @@ export const onlyExportComponents: TSESLint.RuleModule< allowConstantExport: { type: "boolean" }, checkJS: { type: "boolean" }, allowExportNames: { type: "array", items: { type: "string" } }, + createContextMethods: { type: "array", items: { type: "string" } }, }, additionalProperties: false, }, @@ -58,6 +60,7 @@ export const onlyExportComponents: TSESLint.RuleModule< allowConstantExport = false, checkJS = false, allowExportNames, + createContextMethods = [], } = context.options[0] ?? {}; const filename = context.filename; // Skip tests & stories files @@ -79,6 +82,11 @@ export const onlyExportComponents: TSESLint.RuleModule< ? new Set(allowExportNames) : undefined; + const createContextMethods = [ + ...createContextMethods, + "createContext", + ]; + return { Program(program) { let hasExports = false; @@ -133,10 +141,10 @@ export const onlyExportComponents: TSESLint.RuleModule< init.type === "CallExpression" && // createContext || React.createContext ((init.callee.type === "Identifier" && - init.callee.name === "createContext") || + createContextMethodsSet.has(init.callee.name)) || (init.callee.type === "MemberExpression" && init.callee.property.type === "Identifier" && - init.callee.property.name === "createContext")) + createContextMethodsSet.has(init.callee.property.name))) ) { reactContextExports.push(identifierNode); return;