Fix issue with multiple code branches in hooks linter (#14661)
* Fix issue with multiple code branches * Add solution by @calebmer * Add performance test * Undo unrelated change
Yurick committed
Jan 25, 2019 at 15:06 UTC
e19c9e106401fd41c91b67273d4c22289ed0917c
2 files changed
+77
-1
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
+69
@@ -270,6 +270,75 @@ eslintTester.run('react-hooks', ReactHooksESLintRule, {
270
useState();
271
}
272
`,
273
+ `
274
+ // Valid because the loop doesn't change the order of hooks calls.
275
+ function RegressionTest() {
276
+ const res = [];
277
+ const additionalCond = true;
278
+ for (let i = 0; i !== 10 && additionalCond; ++i ) {
279
+ res.push(i);
280
+ }
281
+ React.useLayoutEffect(() => {});
282
+ }
283
+ `,
284
+ `
285
+ // Is valid but hard to compute by brute-forcing
286
+ function MyComponent() {
287
+ // 40 conditions
288
+ if (c) {} else {}
289
+ if (c) {} else {}
290
+ if (c) {} else {}
291
+ if (c) {} else {}
292
+ if (c) {} else {}
293
+ if (c) {} else {}
294
+ if (c) {} else {}
295
+ if (c) {} else {}
296
+ if (c) {} else {}
297
+ if (c) {} else {}
298
+ if (c) {} else {}
299
+ if (c) {} else {}
300
+ if (c) {} else {}
301
+ if (c) {} else {}
302
+ if (c) {} else {}
303
+ if (c) {} else {}
304
+ if (c) {} else {}
305
+ if (c) {} else {}
306
+ if (c) {} else {}
307
+ if (c) {} else {}
308
+ if (c) {} else {}
309
+ if (c) {} else {}
310
+ if (c) {} else {}
311
+ if (c) {} else {}
312
+ if (c) {} else {}
313
+ if (c) {} else {}
314
+ if (c) {} else {}
315
+ if (c) {} else {}
316
+ if (c) {} else {}
317
+ if (c) {} else {}
318
+ if (c) {} else {}
319
+ if (c) {} else {}
320
+ if (c) {} else {}
321
+ if (c) {} else {}
322
+ if (c) {} else {}
323
+ if (c) {} else {}
324
+ if (c) {} else {}
325
+ if (c) {} else {}
326
+ if (c) {} else {}
327
+ if (c) {} else {}
328
+
329
+ // 10 hooks
330
+ useHook();
331
+ useHook();
332
+ useHook();
333
+ useHook();
334
+ useHook();
335
+ useHook();
336
+ useHook();
337
+ useHook();
338
+ useHook();
339
+ useHook();
340
+ }
341
+ `,
342
],
343
invalid: [
344
{
packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
+8
-1
@@ -149,7 +149,14 @@ export default {
149
paths += countPathsFromStart(prevSegment);
150
}
151
}
152
- cache.set(segment.id, paths);
152
+
153
+ // If our segment is reachable then there should be at least one path
154
+ // to it from the start of our code path.
155
+ if (segment.reachable && paths === 0) {
156
+ cache.delete(segment.id);
157
+ } else {
158
+ cache.set(segment.id, paths);
159
+ }
160
161
return paths;
162
}