From e7cd5d3867a943d7ccc5a1ad7ebb4628f4f4ef54 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 19 Apr 2018 18:00:38 -0700 Subject: [PATCH] Throw FlutterError when calling setState in State constructor (#16759) * log error when calling setState in constructor --- .../flutter/lib/src/widgets/framework.dart | 9 +++++ .../test/widgets/set_state_5_test.dart | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 packages/flutter/test/widgets/set_state_5_test.dart diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 00a2cd6f6a..2370498478 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -1103,6 +1103,15 @@ abstract class State extends Diagnosticable { 'consider breaking the reference to this object during dispose().' ); } + if (_debugLifecycleState == _StateLifecycle.created && !mounted) { + throw new FlutterError( + 'setState() called in constructor: $this\n' + 'This happens when you call setState() on a State object for a widget that ' + 'hasn\'t been inserted into the widget tree yet. It is not necessary to call ' + 'setState() in the constructor, since the state is already assumed to be dirty ' + 'when it is initially created.' + ); + } return true; }()); final dynamic result = fn() as dynamic; diff --git a/packages/flutter/test/widgets/set_state_5_test.dart b/packages/flutter/test/widgets/set_state_5_test.dart new file mode 100644 index 0000000000..721e142ca0 --- /dev/null +++ b/packages/flutter/test/widgets/set_state_5_test.dart @@ -0,0 +1,34 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/widgets.dart'; + +class BadWidget extends StatefulWidget { + @override + State createState() => new BadWidgetState(); + +} + +class BadWidgetState extends State { + BadWidgetState() { + setState(() { + _count = 1; + }); + } + + int _count = 0; + + @override + Widget build(BuildContext context) { + return new Text(_count.toString()); + } +} + +void main() { + testWidgets('setState() catches being used inside a constructor', (WidgetTester tester) async { + await tester.pumpWidget(new BadWidget()); + expect(tester.takeException(), const isInstanceOf()); + }); +}