Warn about non-static getDerivedStateFromProps/Catch (#12431)
Dan Abramov committed
Mar 22, 2018 at 17:54 UTC
0af384b4c33bf7d039f513e0869665824e08bb6b
5 files changed
+136
packages/react-reconciler/src/ReactFiberClassComponent.js
+16
@@ -364,6 +364,22 @@ export default function(
364
name,
365
name,
366
);
367
+ const noInstanceGetDerivedStateFromProps =
368
+ typeof instance.getDerivedStateFromProps !== 'function';
369
+ warning(
370
+ noInstanceGetDerivedStateFromProps,
371
+ '%s: getDerivedStateFromProps() is defined as an instance method ' +
372
+ 'and will be ignored. Instead, declare it as a static method.',
373
+ name,
374
+ );
375
+ const noInstanceGetDerivedStateFromCatch =
376
+ typeof instance.getDerivedStateFromCatch !== 'function';
377
+ warning(
378
+ noInstanceGetDerivedStateFromCatch,
379
+ '%s: getDerivedStateFromCatch() is defined as an instance method ' +
380
+ 'and will be ignored. Instead, declare it as a static method.',
381
+ name,
382
+ );
383
const state = instance.state;
384
if (state && (typeof state !== 'object' || isArray(state))) {
385
warning(false, '%s.state: must be set to an object or null', name);
packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee
+22
@@ -118,6 +118,28 @@ describe 'ReactCoffeeScriptClass', ->
118
test React.createElement(Foo, foo: 'foo'), 'DIV', 'foo bar'
119
undefined
120
121
+ it 'warns if getDerivedStateFromProps is not static', ->
122
+ class Foo extends React.Component
123
+ render: ->
124
+ div()
125
+ getDerivedStateFromProps: ->
126
+ {}
127
+ expect(->
128
+ ReactDOM.render(React.createElement(Foo, foo: 'foo'), container)
129
+ ).toWarnDev 'Foo: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.',
130
+ undefined
131
+
132
+ it 'warns if getDerivedStateFromCatch is not static', ->
133
+ class Foo extends React.Component
134
+ render: ->
135
+ div()
136
+ getDerivedStateFromCatch: ->
137
+ {}
138
+ expect(->
139
+ ReactDOM.render(React.createElement(Foo, foo: 'foo'), container)
140
+ ).toWarnDev 'Foo: getDerivedStateFromCatch() is defined as an instance method and will be ignored. Instead, declare it as a static method.',
141
+ undefined
142
+
143
it 'warns if state not initialized before static getDerivedStateFromProps', ->
144
class Foo extends React.Component
145
render: ->
packages/react/src/__tests__/ReactES6Class-test.js
+30
@@ -128,6 +128,36 @@ describe('ReactES6Class', () => {
128
test(<Foo foo="foo" />, 'DIV', 'foo bar');
129
});
130
131
+ it('warns if getDerivedStateFromProps is not static', () => {
132
+ class Foo extends React.Component {
133
+ getDerivedStateFromProps() {
134
+ return {};
135
+ }
136
+ render() {
137
+ return <div />;
138
+ }
139
+ }
140
+ expect(() => ReactDOM.render(<Foo foo="foo" />, container)).toWarnDev(
141
+ 'Foo: getDerivedStateFromProps() is defined as an instance method ' +
142
+ 'and will be ignored. Instead, declare it as a static method.',
143
+ );
144
+ });
145
+
146
+ it('warns if getDerivedStateFromCatch is not static', () => {
147
+ class Foo extends React.Component {
148
+ getDerivedStateFromCatch() {
149
+ return {};
150
+ }
151
+ render() {
152
+ return <div />;
153
+ }
154
+ }
155
+ expect(() => ReactDOM.render(<Foo foo="foo" />, container)).toWarnDev(
156
+ 'Foo: getDerivedStateFromCatch() is defined as an instance method ' +
157
+ 'and will be ignored. Instead, declare it as a static method.',
158
+ );
159
+ });
160
+
161
it('warns if state not initialized before static getDerivedStateFromProps', () => {
162
class Foo extends React.Component {
163
static getDerivedStateFromProps(nextProps, prevState) {
packages/react/src/__tests__/ReactTypeScriptClass-test.ts
+34
@@ -378,6 +378,40 @@ describe('ReactTypeScriptClass', function() {
378
test(React.createElement(Foo, {foo: 'foo'}), 'DIV', 'foo bar');
379
});
380
381
+ it('warns if getDerivedStateFromProps is not static', function() {
382
+ class Foo extends React.Component {
383
+ getDerivedStateFromProps() {
384
+ return {};
385
+ }
386
+ render() {
387
+ return React.createElement('div', {});
388
+ }
389
+ }
390
+ expect(function() {
391
+ ReactDOM.render(React.createElement(Foo, {foo: 'foo'}), container);
392
+ }).toWarnDev(
393
+ 'Foo: getDerivedStateFromProps() is defined as an instance method ' +
394
+ 'and will be ignored. Instead, declare it as a static method.'
395
+ );
396
+ });
397
+
398
+ it('warns if getDerivedStateFromCatch is not static', function() {
399
+ class Foo extends React.Component {
400
+ getDerivedStateFromCatch() {
401
+ return {};
402
+ }
403
+ render() {
404
+ return React.createElement('div');
405
+ }
406
+ }
407
+ expect(function() {
408
+ ReactDOM.render(React.createElement(Foo, {foo: 'foo'}), container);
409
+ }).toWarnDev(
410
+ 'Foo: getDerivedStateFromCatch() is defined as an instance method ' +
411
+ 'and will be ignored. Instead, declare it as a static method.'
412
+ );
413
+ });
414
+
415
it('warns if state not initialized before static getDerivedStateFromProps', function() {
416
class Foo extends React.Component {
417
static getDerivedStateFromProps(nextProps, prevState) {
packages/react/src/__tests__/createReactClassIntegration-test.js
+34
@@ -433,6 +433,40 @@ describe('create-react-class-integration', () => {
433
expect(instance.state.foo).toBe('bar');
434
});
435
436
+ it('warns if getDerivedStateFromProps is not static', () => {
437
+ const Foo = createReactClass({
438
+ getDerivedStateFromProps() {
439
+ return {};
440
+ },
441
+ render() {
442
+ return <div />;
443
+ },
444
+ });
445
+ expect(() =>
446
+ ReactDOM.render(<Foo foo="foo" />, document.createElement('div')),
447
+ ).toWarnDev(
448
+ 'Component: getDerivedStateFromProps() is defined as an instance method ' +
449
+ 'and will be ignored. Instead, declare it as a static method.',
450
+ );
451
+ });
452
+
453
+ it('warns if getDerivedStateFromCatch is not static', () => {
454
+ const Foo = createReactClass({
455
+ getDerivedStateFromCatch() {
456
+ return {};
457
+ },
458
+ render() {
459
+ return <div />;
460
+ },
461
+ });
462
+ expect(() =>
463
+ ReactDOM.render(<Foo foo="foo" />, document.createElement('div')),
464
+ ).toWarnDev(
465
+ 'Component: getDerivedStateFromCatch() is defined as an instance method ' +
466
+ 'and will be ignored. Instead, declare it as a static method.',
467
+ );
468
+ });
469
+
470
it('should warn if state is not properly initialized before getDerivedStateFromProps', () => {
471
const Component = createReactClass({
472
statics: {