mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[WIP] Warn in dev if shouldComponentUpdate is defined on PureComponent (#9240)
* Add test for React.PureComponent * Add warning when shouldComponentUpdate is declared in a PureComponent * Add actionable warning * Add warning in Fiber * Format added code by running yarn prettier * Move pure sCU check to checkClassInstance That way it warns before the component updates
This commit is contained in:
committed by
Brandon Dail
parent
5518bd44a9
commit
ec527cc834
@@ -336,6 +336,7 @@ src/isomorphic/modern/class/__tests__/ReactPureComponent-test.js
|
||||
* should render
|
||||
* can override shouldComponentUpdate
|
||||
* extends React.Component
|
||||
* should warn when shouldComponentUpdate is defined on React.PureComponent
|
||||
|
||||
src/isomorphic/modern/class/__tests__/ReactTypeScriptClass-test.ts
|
||||
* preserves the name of the class for use in error messages
|
||||
|
||||
@@ -64,6 +64,7 @@ describe('ReactPureComponent', () => {
|
||||
});
|
||||
|
||||
it('can override shouldComponentUpdate', () => {
|
||||
spyOn(console, 'error');
|
||||
var renders = 0;
|
||||
class Component extends React.PureComponent {
|
||||
render() {
|
||||
@@ -77,6 +78,13 @@ describe('ReactPureComponent', () => {
|
||||
var container = document.createElement('div');
|
||||
ReactDOM.render(<Component />, container);
|
||||
ReactDOM.render(<Component />, container);
|
||||
expect(console.error.calls.count()).toBe(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).toBe(
|
||||
'Warning: ' +
|
||||
'Component has a method called shouldComponentUpdate(). ' +
|
||||
'shouldComponentUpdate should not be used when extending React.PureComponent. ' +
|
||||
'Please extend React.Component if shouldComponentUpdate is used.',
|
||||
);
|
||||
expect(renders).toBe(2);
|
||||
});
|
||||
|
||||
@@ -93,4 +101,27 @@ describe('ReactPureComponent', () => {
|
||||
ReactDOM.render(<Component />, document.createElement('div'));
|
||||
expect(renders).toBe(1);
|
||||
});
|
||||
|
||||
it('should warn when shouldComponentUpdate is defined on React.PureComponent', () => {
|
||||
spyOn(console, 'error');
|
||||
|
||||
class PureComponent extends React.PureComponent {
|
||||
shouldComponentUpdate() {
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
return <div />;
|
||||
}
|
||||
}
|
||||
var container = document.createElement('div');
|
||||
ReactDOM.render(<PureComponent />, container);
|
||||
|
||||
expect(console.error.calls.count()).toBe(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).toBe(
|
||||
'Warning: ' +
|
||||
'PureComponent has a method called shouldComponentUpdate(). ' +
|
||||
'shouldComponentUpdate should not be used when extending React.PureComponent. ' +
|
||||
'Please extend React.Component if shouldComponentUpdate is used.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -112,6 +112,7 @@ module.exports = function(
|
||||
}
|
||||
|
||||
const instance = workInProgress.stateNode;
|
||||
const type = workInProgress.type;
|
||||
if (typeof instance.shouldComponentUpdate === 'function') {
|
||||
if (__DEV__) {
|
||||
startPhaseTimer(workInProgress, 'shouldComponentUpdate');
|
||||
@@ -137,7 +138,6 @@ module.exports = function(
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
const type = workInProgress.type;
|
||||
if (type.prototype && type.prototype.isPureReactComponent) {
|
||||
return (
|
||||
!shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
|
||||
@@ -149,6 +149,7 @@ module.exports = function(
|
||||
|
||||
function checkClassInstance(workInProgress: Fiber) {
|
||||
const instance = workInProgress.stateNode;
|
||||
const type = workInProgress.type;
|
||||
if (__DEV__) {
|
||||
const name = getComponentName(workInProgress);
|
||||
const renderPresent = instance.render;
|
||||
@@ -203,6 +204,19 @@ module.exports = function(
|
||||
'expected to return a value.',
|
||||
name,
|
||||
);
|
||||
if (
|
||||
type.prototype &&
|
||||
type.prototype.isPureReactComponent &&
|
||||
typeof instance.shouldComponentUpdate !== 'undefined'
|
||||
) {
|
||||
warning(
|
||||
false,
|
||||
'%s has a method called shouldComponentUpdate(). ' +
|
||||
'shouldComponentUpdate should not be used when extending React.PureComponent. ' +
|
||||
'Please extend React.Component if shouldComponentUpdate is used.',
|
||||
getComponentName(workInProgress) || 'A pure component',
|
||||
);
|
||||
}
|
||||
const noComponentDidUnmount =
|
||||
typeof instance.componentDidUnmount !== 'function';
|
||||
warning(
|
||||
|
||||
@@ -299,6 +299,18 @@ var ReactCompositeComponent = {
|
||||
'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
|
||||
this.getName() || 'A component',
|
||||
);
|
||||
if (
|
||||
isPureComponent(Component) &&
|
||||
typeof inst.shouldComponentUpdate !== 'undefined'
|
||||
) {
|
||||
warning(
|
||||
false,
|
||||
'%s has a method called shouldComponentUpdate(). ' +
|
||||
'shouldComponentUpdate should not be used when extending React.PureComponent. ' +
|
||||
'Please extend React.Component if shouldComponentUpdate is used.',
|
||||
this.getName() || 'A pure component',
|
||||
);
|
||||
}
|
||||
warning(
|
||||
!inst.defaultProps,
|
||||
'defaultProps was defined as an instance property on %s. Use a static ' +
|
||||
|
||||
Reference in New Issue
Block a user