# The better way to create  stateful widgets in flutter

Well, since you have come here, I can guess you are looking for some improvements in your coding and code quality. That's great!

Let's take a look at it how we can do it better :

While using the stateful widgets we need to be mindful of rebuilding the widget tree which significantly impacts the performance of your application. Here we will look at an example ( there can be many ways to achieve the same thing). In this example, we will make use of `ValueNotifier` and `ValueListenableBuilder`

## Setup your Flutter project

### Create a Flutter app

* ```dart
      flutter create example_app
    ```
    
* ### Run your app
    

Now, we are done setting up the Flutter app, let's dive into the example.

## Coding Example

In my main.dart file,

```dart
import 'package:flutter/material.dart';

void main() async {
  runApp( const MainApp()); // entry point of your application
}

// In this example, we have a stateless widget 
class MainApp extends StatelessWidget {
  const MainApp({super.key});
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
             child: MySwitch() // MySwitch() is a stateful widget
        ),
      ),
    );
  }
}
```

### What is ValueNotifier and ValueListenableBuilder?

`ValueNotifier` is a class that has a `single generic type` ( which means it can't hold more than one value) that specifies the type of value it holds. When the value it holds is changed it will `trigger` all the `listeners` listening to the changed value.

```dart
  ValueNotifier<bool> switchValue = ValueNotifier<bool>(false);
```

Here I have created a `ValueNotifier` that stores a `boolean` value that has an initial value of `false`.

We can use this `ValueNotifier` which in this case is `switchValue` to listen to the value and trigger the change of value to different available listeners.

`ValueListenableBuilder` is a widget that can `listen` and update the UI based on the `value`.

```dart
ValueListenableBuilder<bool>(
// valueListenable accepts the valueNotifier we have just created
      valueListenable: switchValue, 
// builder gives the current context, current value and the child it has to return
      builder: (BuildContext context, bool value, Widget? child) { 
        return Switch(
// switch takes the boolean value which is returned by builder method
          value: value,  
          onChanged: (newValue) { 
// onChanged return the value opposite to current value. eg 
// if the current value is false, it will return true

// Now we access the value inside of valueNotifier and change it with the value we got from onChanged Method           
 switchValue.value = newValue;  

/// when this value changed the builder method is re-run

          },
        );
      },
    );
```

Now that we understand how it works, let's wrap it up, in a line.

`ValueListenableBuilder` listens to the `ValueNotifier` that has a single generic value, on change of which `ValueListenableBuilder` will re-run the `builder` method, which reflects the change in UI without rebuilding the whole `widget tree`.

Full Code:

```dart
import 'package:flutter/material.dart';

void main() async {
  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: MySwitch()),
      ),
    );
  }
}

class MySwitch extends StatefulWidget {
  @override
  _MySwitchState createState() => _MySwitchState();
}

class _MySwitchState extends State<MySwitch> {
  ValueNotifier<bool> switchValue = ValueNotifier<bool>(false);

  @override
  void dispose() {
    switchValue.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print("Widget rebuilding");
    return ValueListenableBuilder<bool>(
      valueListenable: switchValue,
      builder: (BuildContext context, bool value, Widget? child) {
        return Switch(
          value: value,
          onChanged: (newValue) {
            switchValue.value = newValue;
          },
        );
      },
    );
  }
}
```

I hope you got value out of this, if you did, you can subscribe to the newsletter that I will put out with updates and best practices.😉 For more, content like this, visit [Flutter World](https://www.flutterworld.tech/).
