Introduction

Flutter's hot reload feature preserves the state of your app by reusing existing State objects. However, when you add new fields to a State class and hot reload, those new fields are not initialized because the existing State instance is reused rather than recreated. This leads to null reference errors, unexpected behavior, or silent bugs where new fields retain default values instead of being properly initialized.

Symptoms

  • After hot reload, newly added fields are null or uninitialized
  • NoSuchMethodError: The getter 'x' was called on null
  • Hot reload succeeds but app behavior is incorrect
  • Console warning:
  • `
  • Warning: A State object's initState was not called during hot reload.
  • The State object was not recreated, so initState will not be called again.
  • `
  • Hot restart fixes the issue, but you want to avoid restarting

Common Causes

  • Adding instance variables to a State class without initializing them
  • Adding new members that depend on widget properties that are set in initState
  • Changing the constructor signature of a StatefulWidget without updating state initialization
  • Modifying final fields in State after initial creation

Step-by-Step Fix

  1. 1.Understand when hot reload preserves state:
  2. 2.- Hot reload reuses existing State objects
  3. 3.- New fields added to State will have their default values (null for objects)
  4. 4.- initState() is NOT called during hot reload
  5. 5.- Only the build() method is re-executed
  6. 6.For nullable fields, add null checks after hot reload:
  7. 7.```dart
  8. 8.class _CounterState extends State<Counter> {
  9. 9.int? _newField; // Added during hot reload - will be null

@override Widget build(BuildContext context) { // Safe check for field added during hot reload final value = _newField ?? 0; return Text('Value: $value'); } } ```

  1. 1.Use late initialization with guards:
  2. 2.```dart
  3. 3.class _MyState extends State<MyWidget> {
  4. 4.late final DataProcessor _processor;
  5. 5.bool _isInitialized = false;

@override void initState() { super.initState(); _initialize(); }

void _initialize() { _processor = DataProcessor(widget.config); _isInitialized = true; }

@override Widget build(BuildContext context) { if (!_isInitialized) { _initialize(); // Handle field added during hot reload } return Text(_processor.process()); } } ```

  1. 1.When state is corrupted, perform a hot restart:
  2. 2.```bash
  3. 3.# In the running flutter run terminal:
  4. 4.# Press 'R' for hot restart (capital R), not 'r' for hot reload
  5. 5.`
  6. 6.Or from command line:
  7. 7.```bash
  8. 8.flutter run --hot
  9. 9.# Then press R in the terminal
  10. 10.`
  11. 11.Use a state management solution that survives hot reload:
  12. 12.```dart
  13. 13.// Riverpod example - providers survive hot reload better
  14. 14.@riverpod
  15. 15.class Counter extends _$Counter {
  16. 16.@override
  17. 17.int build() => 0;

void increment() => state++; } ```

Prevention

  • Perform a hot restart (R) instead of hot reload (r) after adding new fields
  • Use nullable types for fields that might be uninitialized during development
  • Consider using state management (Riverpod, Provider) for complex state
  • Use flutter run --hot and learn the difference between 'r' and 'R'
  • Save state to disk or use RestorationMixin for state that needs to survive restarts