Skip to content

Commit e02086b

Browse files
committed
Warn about variable number of dependencies
We don't check this in prod, since best practice is to always pass these inline. But we should still warn in dev.
1 parent b92cdef commit e02086b

3 files changed

Lines changed: 71 additions & 2 deletions

File tree

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
} from './ReactFiberScheduler';
3838

3939
import invariant from 'shared/invariant';
40+
import warning from 'shared/warning';
4041
import warningWithoutStack from 'shared/warningWithoutStack';
4142
import {enableDispatchCallback_DEPRECATED} from 'shared/ReactFeatureFlags';
4243

@@ -760,8 +761,19 @@ function dispatchAction<S, A>(
760761
}
761762

762763
function inputsAreEqual(arr1, arr2) {
763-
// Don't bother comparing lengths because these arrays are always
764+
// Don't bother comparing lengths in prod because these arrays should be
764765
// passed inline.
766+
if (__DEV__) {
767+
warning(
768+
arr1.length === arr2.length,
769+
'Detected a variable number of hook dependencies. The length of the ' +
770+
'dependencies array should be constant between renders.\n\n' +
771+
'Previous: %s\n' +
772+
'Incoming: %s',
773+
arr1.join(', '),
774+
arr2.join(', '),
775+
);
776+
}
765777
for (let i = 0; i < arr1.length; i++) {
766778
// Inlined Object.is polyfill.
767779
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright (c) 2013-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @emails react-core
8+
* @jest-environment node
9+
*/
10+
11+
/* eslint-disable no-func-assign */
12+
13+
'use strict';
14+
15+
let React;
16+
let ReactFeatureFlags;
17+
let ReactTestRenderer;
18+
19+
// Additional tests can be found in ReactHooksWithNoopRenderer. Plan is to
20+
// gradually migrate those to this file.
21+
describe('ReactHooks', () => {
22+
beforeEach(() => {
23+
jest.resetModules();
24+
25+
ReactFeatureFlags = require('shared/ReactFeatureFlags');
26+
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
27+
ReactFeatureFlags.enableHooks = true;
28+
React = require('react');
29+
ReactTestRenderer = require('react-test-renderer');
30+
});
31+
32+
it('warns about variable number of dependencies', () => {
33+
const {useLayoutEffect} = React;
34+
function App(props) {
35+
useLayoutEffect(() => {
36+
ReactTestRenderer.unstable_yield(
37+
'Did commit: ' + props.dependencies.join(', '),
38+
);
39+
}, props.dependencies);
40+
return props.dependencies;
41+
}
42+
const root = ReactTestRenderer.create(<App dependencies={['A']} />);
43+
expect(ReactTestRenderer).toHaveYielded(['Did commit: A']);
44+
expect(() => {
45+
root.update(<App dependencies={['A', 'B']} />);
46+
}).toWarnDev([
47+
'Warning: Detected a variable number of hook dependencies. The length ' +
48+
'of the dependencies array should be constant between renders.\n\n' +
49+
'Previous: A, B\n' +
50+
'Incoming: A',
51+
]);
52+
expect(ReactTestRenderer).toHaveYielded(['Did commit: A, B']);
53+
});
54+
});

packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ let forwardRef;
2929
let flushPassiveEffects;
3030
let memo;
3131

32-
describe('ReactHooks', () => {
32+
// These tests use React Noop Renderer. All new tests should use React Test
33+
// Renderer and go in ReactHooks-test; plan is gradually migrate the noop tests
34+
// to that file.
35+
describe('ReactHooksWithNoopRenderer', () => {
3336
beforeEach(() => {
3437
jest.resetModules();
3538

0 commit comments

Comments
 (0)