Skip to content

Commit 97bdd56

Browse files
authored
Report React context exports (#54)
1 parent 268df3b commit 97bdd56

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

src/only-export-components.test.ts

+17
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,18 @@ const valid = [
177177
name: "Allow connect from react-redux",
178178
code: "const MyComponent = () => {}; export default connect(() => ({}))(MyComponent);",
179179
},
180+
{
181+
name: "Two components, one of them with 'Context' in its name",
182+
code: "export const MyComponent = () => {}; export const ChatContext = () => {};",
183+
},
184+
{
185+
name: "Component & local React context",
186+
code: "export const MyComponent = () => {}; const MyContext = createContext('test');",
187+
},
188+
{
189+
name: "Only React context",
190+
code: "export const MyContext = createContext('test');",
191+
},
180192
];
181193

182194
const invalid = [
@@ -273,6 +285,11 @@ const invalid = [
273285
code: 'const Foo = () => {}; export { Foo as "🍌"}',
274286
errorId: "localComponents",
275287
},
288+
{
289+
name: "Component and React Context",
290+
code: "export const MyComponent = () => {}; export const MyContext = createContext('test');",
291+
errorId: "reactContext",
292+
},
276293
];
277294

278295
const it = (name: string, cases: Parameters<typeof ruleTester.run>[2]) => {

src/only-export-components.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export const onlyExportComponents: TSESLint.RuleModule<
1313
| "namedExport"
1414
| "anonymousExport"
1515
| "noExport"
16-
| "localComponents",
16+
| "localComponents"
17+
| "reactContext",
1718
| []
1819
| [
1920
{
@@ -35,6 +36,8 @@ export const onlyExportComponents: TSESLint.RuleModule<
3536
"Fast refresh only works when a file only exports components. Move your component(s) to a separate file.",
3637
noExport:
3738
"Fast refresh only works when a file has exports. Move your component(s) to a separate file.",
39+
reactContext:
40+
"Fast refresh only works when a file only exports components. Move your React context(s) to a separate file.",
3841
},
3942
type: "problem",
4043
schema: [
@@ -56,7 +59,7 @@ export const onlyExportComponents: TSESLint.RuleModule<
5659
checkJS = false,
5760
allowExportNames,
5861
} = context.options[0] ?? {};
59-
const filename = context.getFilename();
62+
const filename = context.filename;
6063
// Skip tests & stories files
6164
if (
6265
filename.includes(".test.") ||
@@ -86,6 +89,7 @@ export const onlyExportComponents: TSESLint.RuleModule<
8689
| TSESTree.BindingName
8790
| TSESTree.StringLiteral
8891
)[] = [];
92+
const reactContextExports: TSESTree.Identifier[] = [];
8993

9094
const handleLocalIdentifier = (
9195
identifierNode: TSESTree.BindingName,
@@ -124,6 +128,15 @@ export const onlyExportComponents: TSESLint.RuleModule<
124128
nonComponentExports.push(identifierNode);
125129
}
126130
} else {
131+
if (
132+
init &&
133+
init.type === "CallExpression" &&
134+
init.callee.type === "Identifier" &&
135+
init.callee.name === "createContext"
136+
) {
137+
reactContextExports.push(identifierNode);
138+
return;
139+
}
127140
if (
128141
init &&
129142
// Switch to allowList?
@@ -263,6 +276,9 @@ export const onlyExportComponents: TSESLint.RuleModule<
263276
for (const node of nonComponentExports) {
264277
context.report({ messageId: "namedExport", node });
265278
}
279+
for (const node of reactContextExports) {
280+
context.report({ messageId: "reactContext", node });
281+
}
266282
} else if (localComponents.length) {
267283
for (const node of localComponents) {
268284
context.report({ messageId: "localComponents", node });

0 commit comments

Comments
 (0)