From 6f9a9cf73d43215f3be78ee82f499d738fc23783 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 13 Aug 2019 00:22:19 +0200 Subject: [PATCH] Warn when calling setState in a constructor (#1857) --- debug/src/debug.js | 14 +++++++++++++- debug/test/browser/debug.test.js | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/debug/src/debug.js b/debug/src/debug.js index 24e1283c878..2e1e1670de2 100644 --- a/debug/src/debug.js +++ b/debug/src/debug.js @@ -1,6 +1,6 @@ import { checkPropTypes } from './check-props'; import { getDisplayName } from './devtools/custom'; -import { options } from 'preact'; +import { options, Component } from 'preact'; import { ELEMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE } from './constants'; function getClosestDomNodeParent(parent) { @@ -260,6 +260,18 @@ export function initDebug() { }; } +const setState = Component.prototype.setState; +Component.prototype.setState = function(update, callback) { + if (this._vnode==null) { + console.warn( + `Calling "this.setState" inside the constructor of a component is a ` + + `no-op and might be a bug in your application. Instead, set ` + + `"this.state = {}" directly.` + ); + } + return setState.call(this, update, callback); +}; + /** * Serialize a vnode tree to a string * @param {import('./internal').VNode} vnode diff --git a/debug/test/browser/debug.test.js b/debug/test/browser/debug.test.js index 0c855b03310..d3551ad1760 100644 --- a/debug/test/browser/debug.test.js +++ b/debug/test/browser/debug.test.js @@ -205,6 +205,22 @@ describe('debug', () => { expect(fn).to.throw(/createElement/); }); + it('should warn when calling setState inside the constructor', () => { + class Foo extends Component { + constructor(props) { + super(props); + this.setState({ foo: true }); + } + render() { + return
foo
; + } + } + + render(, scratch); + expect(console.warn).to.be.calledOnce; + expect(console.warn.args[0]).to.match(/no-op/); + }); + it('should warn for useless useMemo calls', () => { const App = () => { const [people] = useState([40, 20, 60, 80]);