Alternatives to `setState` in Flutter | 1

 # Alternatives to `setState` in Flutter


## Introduction

Flutter provides several ways to manage state in applications. While `setState` is commonly used for stateful widgets, there are other built-in approaches that can be more efficient and scalable without relying on external packages. In this blog, we will explore different alternatives to `setState` within Flutter itself.


---

## 1. Using `ValueNotifier` and `ValueListenableBuilder`

`ValueNotifier` is a special type of `ChangeNotifier` that helps manage state reactively without excessive widget rebuilds.


### Example:

```dart

class CounterScreen extends StatelessWidget {

  final ValueNotifier<int> counter = ValueNotifier<int>(0);


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text("Counter")),

      body: Center(

        child: ValueListenableBuilder<int>(

          valueListenable: counter,

          builder: (context, value, child) {

            return Text("Count: $value", style: TextStyle(fontSize: 24));

          },

        ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: () => counter.value++,

        child: Icon(Icons.add),

      ),

    );

  }

}

```


---

## 2. Using `InheritedWidget`

`InheritedWidget` allows state to be passed efficiently down the widget tree without explicitly passing parameters.


### Example:

```dart

class CounterProvider extends InheritedWidget {

  final int count;

  final Function() increment;


  const CounterProvider({

    required Widget child,

    required this.count,

    required this.increment,

  }) : super(child: child);


  static CounterProvider? of(BuildContext context) =>

      context.dependOnInheritedWidgetOfExactType<CounterProvider>();


  @override

  bool updateShouldNotify(CounterProvider oldWidget) => count != oldWidget.count;

}

```


Usage in Widget:

```dart

class CounterScreen extends StatefulWidget {

  @override

  _CounterScreenState createState() => _CounterScreenState();

}


class _CounterScreenState extends State<CounterScreen> {

  int _count = 0;


  void _increment() {

    setState(() {

      _count++;

    });

  }


  @override

  Widget build(BuildContext context) {

    return CounterProvider(

      count: _count,

      increment: _increment,

      child: CounterView(),

    );

  }

}


class CounterView extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    final provider = CounterProvider.of(context);

    return Scaffold(

      appBar: AppBar(title: Text("InheritedWidget Counter")),

      body: Center(

        child: Text("Count: ${provider?.count}", style: TextStyle(fontSize: 24)),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: provider?.increment,

        child: Icon(Icons.add),

      ),

    );

  }

}

```


---

## 3. Using `StreamBuilder`

Streams provide a way to handle state changes asynchronously.


### Example:

```dart

class CounterBloc {

  final _controller = StreamController<int>();

  int _counter = 0;


  Stream<int> get counterStream => _controller.stream;


  void increment() {

    _counter++;

    _controller.sink.add(_counter);

  }


  void dispose() {

    _controller.close();

  }

}

```


Usage in Widget:

```dart

class CounterScreen extends StatelessWidget {

  final CounterBloc bloc = CounterBloc();


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text("StreamBuilder Counter")),

      body: Center(

        child: StreamBuilder<int>(

          stream: bloc.counterStream,

          initialData: 0,

          builder: (context, snapshot) {

            return Text("Count: ${snapshot.data}", style: TextStyle(fontSize: 24));

          },

        ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: bloc.increment,

        child: Icon(Icons.add),

      ),

    );

  }

}

```


---

## Conclusion

While `setState` is useful for simple state management, alternatives like `ValueNotifier`, `InheritedWidget`, and `StreamBuilder` offer more efficient and scalable solutions within Flutter itself. Choosing the right method depends on your app's complexity and performance needs.


Do you use any of these alternatives in your projects? Let us know in the comments!