NativeMethodsMixin DEV-only methods should not warn (#12212)
* Disable DEV-only warnings for RN NativeMethodsMixin/create-react-class * Tiny bit of cleanup * Make strict-mode suppression check a little more robust
Brian Vaughn committed
Feb 11, 2018 at 16:29 UTC
86ee9e84880cab9f3804e7e59ec75bb75a4cf455
3 files changed
+69
-10
packages/react-native-renderer/src/NativeMethodsMixin.js
+8
@@ -192,6 +192,8 @@ if (__DEV__) {
192
!NativeMethodsMixin_DEV.UNSAFE_componentWillReceiveProps,
193
'Do not override existing functions.',
194
);
195
+ // TODO (bvaughn) Remove cWM and cWRP in a future version of React Native,
196
+ // Once these lifecycles have been remove from the reconciler.
197
NativeMethodsMixin_DEV.componentWillMount = function() {
198
throwOnStylesProp(this, this.props);
199
};
@@ -204,6 +206,12 @@ if (__DEV__) {
206
NativeMethodsMixin_DEV.UNSAFE_componentWillReceiveProps = function(newProps) {
207
throwOnStylesProp(this, newProps);
208
};
209
+
210
+ // React may warn about cWM/cWRP/cWU methods being deprecated.
211
+ // Add a flag to suppress these warnings for this special case.
212
+ // TODO (bvaughn) Remove this flag once the above methods have been removed.
213
+ NativeMethodsMixin_DEV.componentWillMount.__suppressDeprecationWarning = true;
214
+ NativeMethodsMixin_DEV.componentWillReceiveProps.__suppressDeprecationWarning = true;
215
}
216
217
export default NativeMethodsMixin;
packages/react-reconciler/src/ReactStrictModeWarnings.js
+5
-8
@@ -201,19 +201,16 @@ if (__DEV__) {
201
}
202
203
// Don't warn about react-lifecycles-compat polyfilled components.
204
- // Note that it is sufficient to check for the presence of a
205
- // single lifecycle, componentWillMount, with the polyfill flag.
204
if (
205
typeof instance.componentWillMount === 'function' &&
208
- instance.componentWillMount.__suppressDeprecationWarning === true
206
+ instance.componentWillMount.__suppressDeprecationWarning !== true
207
) {
210
- return;
211
- }
212
-
213
- if (typeof instance.componentWillMount === 'function') {
208
pendingComponentWillMountWarnings.push(fiber);
209
}
216
- if (typeof instance.componentWillReceiveProps === 'function') {
210
+ if (
211
+ typeof instance.componentWillReceiveProps === 'function' &&
212
+ instance.componentWillReceiveProps.__suppressDeprecationWarning !== true
213
+ ) {
214
pendingComponentWillReceivePropsWarnings.push(fiber);
215
}
216
if (typeof instance.componentWillUpdate === 'function') {
packages/react/src/__tests__/createReactClassIntegration-test.internal.js
+56
-2
@@ -10,17 +10,17 @@
10
'use strict';
11
12
let React;
13
-let ReactDOM;
13
let ReactFeatureFlags;
14
let createReactClass;
15
16
describe('create-react-class-integration', () => {
17
beforeEach(() => {
18
+ jest.resetModules();
19
+
20
ReactFeatureFlags = require('shared/ReactFeatureFlags');
21
ReactFeatureFlags.warnAboutDeprecatedLifecycles = true;
22
23
React = require('react');
23
- ReactDOM = require('react-dom');
24
createReactClass = require('create-react-class/factory')(
25
React.Component,
26
React.isValidElement,
@@ -31,6 +31,8 @@ describe('create-react-class-integration', () => {
31
// TODO (RFC #6) Merge this back into createReactClassIntegration-test once
32
// the 'warnAboutDeprecatedLifecycles' feature flag has been removed.
33
it('isMounted works', () => {
34
+ const ReactDOM = require('react-dom');
35
+
36
const ops = [];
37
let instance;
38
const Component = createReactClass({
@@ -113,4 +115,56 @@ describe('create-react-class-integration', () => {
115
'after unmount: false',
116
]);
117
});
118
+
119
+ describe('ReactNative NativeMethodsMixin', () => {
120
+ let ReactNative;
121
+ let NativeMethodsMixin;
122
+
123
+ beforeEach(() => {
124
+ ReactNative = require('react-native-renderer');
125
+ NativeMethodsMixin =
126
+ ReactNative.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
127
+ .NativeMethodsMixin;
128
+ });
129
+
130
+ it('should not warn about default DEV-only legacy lifecycle methods', () => {
131
+ const View = createReactClass({
132
+ mixins: [NativeMethodsMixin],
133
+ render: () => null,
134
+ });
135
+
136
+ ReactNative.render(<View />, 1);
137
+ });
138
+
139
+ it('should warn if users specify their own legacy componentWillMount', () => {
140
+ const View = createReactClass({
141
+ displayName: 'MyNativeComponent',
142
+ mixins: [NativeMethodsMixin],
143
+ componentWillMount: () => {},
144
+ render: () => null,
145
+ });
146
+
147
+ expect(() => ReactNative.render(<View />, 1)).toLowPriorityWarnDev(
148
+ 'componentWillMount is deprecated and will be removed in the next major version. ' +
149
+ 'Use componentDidMount instead. As a temporary workaround, ' +
150
+ 'you can rename to UNSAFE_componentWillMount.' +
151
+ '\n\nPlease update the following components: MyNativeComponent',
152
+ );
153
+ });
154
+
155
+ it('should warn if users specify their own legacy componentWillReceiveProps', () => {
156
+ const View = createReactClass({
157
+ displayName: 'MyNativeComponent',
158
+ mixins: [NativeMethodsMixin],
159
+ componentWillReceiveProps: () => {},
160
+ render: () => null,
161
+ });
162
+
163
+ expect(() => ReactNative.render(<View />, 1)).toLowPriorityWarnDev(
164
+ 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' +
165
+ 'Use static getDerivedStateFromProps instead.' +
166
+ '\n\nPlease update the following components: MyNativeComponent',
167
+ );
168
+ });
169
+ });
170
});