Skip to content

Commit e709e30

Browse files
committed
Added unsafe_* lifecycles and deprecation warnings
If the old lifecycle hooks (componentWillMount, componentWillUpdate, componentWillReceiveProps) are detected, these methods will be called and a deprecation warning will be logged. (In other words, we do not check for both the presence of the old and new lifecycles.) This commit is expected to fail tests.
1 parent 4f309f8 commit e709e30

File tree

3 files changed

+132
-29
lines changed

3 files changed

+132
-29
lines changed

packages/react-dom/src/server/ReactPartialRenderer.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,18 @@ function resolve(
457457
if (initialState === undefined) {
458458
inst.state = initialState = null;
459459
}
460-
if (inst.componentWillMount) {
461-
inst.componentWillMount();
460+
if (inst.unsafe_componentWillMount || inst.componentWillMount) {
461+
if (inst.componentWillMount) {
462+
warning(
463+
false,
464+
'%s: componentWillMount() is deprecated and will be removed in the ' +
465+
'next major version. Please use unsafe_componentWillMount() instead.',
466+
getComponentName(Component) || 'Unknown',
467+
);
468+
inst.componentWillMount();
469+
} else {
470+
inst.unsafe_componentWillMount();
471+
}
462472
if (queue.length) {
463473
oldQueue = queue;
464474
oldReplace = replace;

packages/react-reconciler/src/ReactFiberClassComponent.js

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,21 @@ export default function(
392392
function callComponentWillMount(workInProgress, instance) {
393393
startPhaseTimer(workInProgress, 'componentWillMount');
394394
const oldState = instance.state;
395-
instance.componentWillMount();
395+
396+
if (typeof instance.componentWillMount === 'function') {
397+
if (__DEV__) {
398+
warning(
399+
false,
400+
'%s: componentWillMount() is deprecated and will be removed in the ' +
401+
'next major version. Please use unsafe_componentWillMount() instead.',
402+
getComponentName(workInProgress),
403+
);
404+
}
405+
instance.componentWillMount();
406+
} else {
407+
instance.unsafe_componentWillMount();
408+
}
409+
396410
stopPhaseTimer();
397411

398412
if (oldState !== instance.state) {
@@ -415,14 +429,29 @@ export default function(
415429
newProps,
416430
newContext,
417431
) {
418-
startPhaseTimer(workInProgress, 'componentWillReceiveProps');
419432
const oldState = instance.state;
420-
instance.componentWillReceiveProps(newProps, newContext);
421-
stopPhaseTimer();
433+
if (typeof instance.componentWillReceiveProps === 'function') {
434+
if (__DEV__) {
435+
warning(
436+
false,
437+
'%s: componentWillReceiveProps() is deprecated and will be removed in the ' +
438+
'next major version. Please use unsafe_componentWillReceiveProps() instead.',
439+
getComponentName(workInProgress),
440+
);
441+
}
422442

423-
// Simulate an async bailout/interruption by invoking lifecycle twice.
424-
if (debugRenderPhaseSideEffects) {
443+
startPhaseTimer(workInProgress, 'componentWillReceiveProps');
425444
instance.componentWillReceiveProps(newProps, newContext);
445+
stopPhaseTimer();
446+
} else {
447+
startPhaseTimer(workInProgress, 'componentWillReceiveProps');
448+
instance.unsafe_componentWillReceiveProps(newProps, newContext);
449+
stopPhaseTimer();
450+
451+
// Simulate an async bailout/interruption by invoking lifecycle twice.
452+
if (debugRenderPhaseSideEffects) {
453+
instance.unsafe_componentWillReceiveProps(newProps, newContext);
454+
}
426455
}
427456

428457
if (instance.state !== oldState) {
@@ -473,7 +502,10 @@ export default function(
473502
workInProgress.internalContextTag |= AsyncUpdates;
474503
}
475504

476-
if (typeof instance.componentWillMount === 'function') {
505+
if (
506+
typeof instance.unsafe_componentWillMount === 'function' ||
507+
typeof instance.componentWillMount === 'function'
508+
) {
477509
callComponentWillMount(workInProgress, instance);
478510
// If we had additional state updates during this life-cycle, let's
479511
// process them now.
@@ -619,7 +651,8 @@ export default function(
619651
// during componentDidUpdate we pass the "current" props.
620652

621653
if (
622-
typeof instance.componentWillReceiveProps === 'function' &&
654+
(typeof instance.unsafe_componentWillReceiveProps === 'function' ||
655+
typeof instance.componentWillReceiveProps === 'function') &&
623656
(oldProps !== newProps || oldContext !== newContext)
624657
) {
625658
callComponentWillReceiveProps(
@@ -679,14 +712,32 @@ export default function(
679712
);
680713

681714
if (shouldUpdate) {
682-
if (typeof instance.componentWillUpdate === 'function') {
683-
startPhaseTimer(workInProgress, 'componentWillUpdate');
684-
instance.componentWillUpdate(newProps, newState, newContext);
685-
stopPhaseTimer();
686-
687-
// Simulate an async bailout/interruption by invoking lifecycle twice.
688-
if (debugRenderPhaseSideEffects) {
715+
if (
716+
typeof instance.unsafe_componentWillUpdate === 'function' ||
717+
typeof instance.componentWillUpdate === 'function'
718+
) {
719+
if (typeof instance.componentWillUpdate === 'function') {
720+
if (__DEV__) {
721+
warning(
722+
false,
723+
'%s: componentWillUpdate() is deprecated and will be removed in the ' +
724+
'next major version. Please use unsafe_componentWillUpdate() instead.',
725+
getComponentName(workInProgress),
726+
);
727+
}
728+
729+
startPhaseTimer(workInProgress, 'componentWillUpdate');
689730
instance.componentWillUpdate(newProps, newState, newContext);
731+
stopPhaseTimer();
732+
} else {
733+
startPhaseTimer(workInProgress, 'componentWillUpdate');
734+
instance.unsafe_componentWillUpdate(newProps, newState, newContext);
735+
stopPhaseTimer();
736+
737+
// Simulate an async bailout/interruption by invoking lifecycle twice.
738+
if (debugRenderPhaseSideEffects) {
739+
instance.unsafe_componentWillUpdate(newProps, newState, newContext);
740+
}
690741
}
691742
}
692743
if (typeof instance.componentDidUpdate === 'function') {

packages/react-test-renderer/src/ReactShallowRenderer.js

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import emptyObject from 'fbjs/lib/emptyObject';
1313
import invariant from 'fbjs/lib/invariant';
1414
import shallowEqual from 'fbjs/lib/shallowEqual';
1515
import checkPropTypes from 'prop-types/checkPropTypes';
16+
import warning from 'fbjs/lib/warning';
1617

1718
class ReactShallowRenderer {
1819
static createRenderer = function() {
@@ -73,7 +74,7 @@ class ReactShallowRenderer {
7374
this._context = getMaskedContext(element.type.contextTypes, context);
7475

7576
if (this._instance) {
76-
this._updateClassComponent(element.type, element.props, this._context);
77+
this._updateClassComponent(element, this._context);
7778
} else {
7879
if (shouldConstruct(element.type)) {
7980
this._instance = new element.type(
@@ -96,7 +97,7 @@ class ReactShallowRenderer {
9697
currentlyValidatingElement = null;
9798
}
9899

99-
this._mountClassComponent(element.props, this._context);
100+
this._mountClassComponent(element, this._context);
100101
} else {
101102
this._rendered = element.type(element.props, this._context);
102103
}
@@ -122,16 +123,31 @@ class ReactShallowRenderer {
122123
this._instance = null;
123124
}
124125

125-
_mountClassComponent(props, context) {
126+
_mountClassComponent(element, context) {
126127
this._instance.context = context;
127-
this._instance.props = props;
128+
this._instance.props = element.props;
128129
this._instance.state = this._instance.state || null;
129130
this._instance.updater = this._updater;
130131

131-
if (typeof this._instance.componentWillMount === 'function') {
132+
if (
133+
typeof this._instance.unsafe_componentWillMount === 'function' ||
134+
typeof this._instance.componentWillMount === 'function'
135+
) {
132136
const beforeState = this._newState;
133137

134-
this._instance.componentWillMount();
138+
if (typeof this._instance.componentWillMount === 'function') {
139+
if (__DEV__) {
140+
warning(
141+
false,
142+
'%s: componentWillMount() is deprecated and will be removed in the ' +
143+
'next major version. Please use unsafe_componentWillMount() instead.',
144+
getName(element.type, this._instance),
145+
);
146+
}
147+
this._instance.componentWillMount();
148+
} else {
149+
this._instance.unsafe_componentWillMount();
150+
}
135151

136152
// setState may have been called during cWM
137153
if (beforeState !== this._newState) {
@@ -144,15 +160,28 @@ class ReactShallowRenderer {
144160
// because DOM refs are not available.
145161
}
146162

147-
_updateClassComponent(type, props, context) {
163+
_updateClassComponent(element, context) {
164+
const {props, type} = element;
165+
148166
const oldState = this._instance.state || emptyObject;
149167
const oldProps = this._instance.props;
150168

151-
if (
152-
oldProps !== props &&
153-
typeof this._instance.componentWillReceiveProps === 'function'
154-
) {
155-
this._instance.componentWillReceiveProps(props, context);
169+
if (oldProps !== props) {
170+
if (typeof this._instance.componentWillReceiveProps === 'function') {
171+
if (__DEV__) {
172+
warning(
173+
false,
174+
'%s: componentWillReceiveProps() is deprecated and will be removed in the ' +
175+
'next major version. Please use unsafe_componentWillReceiveProps() instead.',
176+
getName(element.type, this._instance),
177+
);
178+
}
179+
this._instance.componentWillReceiveProps(props, context);
180+
} else if (
181+
typeof this._instance.unsafe_componentWillReceiveProps === 'function'
182+
) {
183+
this._instance.unsafe_componentWillReceiveProps(props, context);
184+
}
156185
}
157186
// Read state after cWRP in case it calls setState
158187
const state = this._newState || oldState;
@@ -174,7 +203,20 @@ class ReactShallowRenderer {
174203

175204
if (shouldUpdate) {
176205
if (typeof this._instance.componentWillUpdate === 'function') {
206+
if (__DEV__) {
207+
warning(
208+
false,
209+
'%s: componentWillUpdate() is deprecated and will be removed in the ' +
210+
'next major version. Please use unsafe_componentWillUpdate() instead.',
211+
getName(element.type, this._instance),
212+
);
213+
}
214+
177215
this._instance.componentWillUpdate(props, state, context);
216+
} else if (
217+
typeof this._instance.unsafe_componentWillUpdate === 'function'
218+
) {
219+
this._instance.unsafe_componentWillUpdate(props, state, context);
178220
}
179221
}
180222

0 commit comments

Comments
 (0)