Create Switch Case Kind Widget in Flutter
Tags: flutter, dart, tutorial, mobile
Published: 2023-05-17 17:15:30

Welcome back guys,Today we are going to learn some new quick technique by which we can enhance our flutter code readability.

We are going to create own Switch-Case like conditional widgets or same like [bloc state](https://pub.dev/packages/flutter_bloc) (builder).

We will be going through basics,

## What is Switch-Case?
In Dart, the switch statement is used for conditional branching based on the value of a variable. It provides a convenient way to execute different code blocks based on the value of an expression. The structure of a switch statement in Dart is as follows
```
switch (expression) {
  case value1:
    // Code to execute if expression matches value1
    break;
  case value2:
    // Code to execute if expression matches value2
    break;
  // Additional cases
  default:
    // Code to execute if none of the cases match the expression
}
```

## Conditional Widget

In flutter, for example on the basis of condition you have to hide or show some widget,for example loading indicator so for that we can use [visibility](https://api.flutter.dev/flutter/widgets/Visibility-class.html) widget,if-else, or ternary operators.

## If we have options then why we need switch case widget

- Visibility: we know that visible hide the specified on widget on given `boolean` value,for example
```
 Visibility(
   visible: false,
   child: Text("Hello,world")),
```
it is obviously good option but it will not work on multiple choices  and it can be either Widget A or Widget B (if replacement specified).

- if else or ternary operator: if else/ternary operator are useful to show conditional widget but when the no of cases increase it become difficult to read.

## Solution ??

![meme 1](https://i.redd.it/if3ldk2w2j841.jpg)


for that we are going to create Switch-case like custom widget 

-  Creating Custom StatelessWidget `SwitchCaseWidget`:
```
class SwitchCaseWidget<T> extends StatelessWidget {
  final Widget? Function(T? t) stateBuilder;
  final T activeState;

  const SwitchCaseWidget({
    super.key,
    required this.stateBuilder,
    required this.activeState,
  });

  @override
  Widget build(BuildContext context) {
    return stateBuilder(activeState) ?? const SizedBox.shrink();
  }
}
```
Let's go through each part of the `SwitchCaseWidget` class and its functionality:

1. `class SwitchCaseWidget<T> extends StatelessWidget`: This line defines a Dart class named `SwitchCaseWidget` that is generic over a type `T`. It extends the `StatelessWidget` class, indicating that this widget does not have any mutable state.

2. `final Widget? Function(T? t) stateBuilder;`: It represents a function that takes a value of type `T` or nullable `T` and returns a widget or `null`. The function will be responsible for determining the widget to return based on the value passed to it.

3. `final T activeState;`: This line declares a final variable `value` of type `T`. It represents the value that will be passed to the `stateBuilder` function to determine the widget.

The purpose of the `SwitchCaseWidget` class is to simplify the process of creating widgets based on different cases or values. By providing a `cases` function and a value, you can dynamically determine and render different widgets based on the provided value.

- Before use it let's create states possible,
 for the following example I am going to have 3 states,
   - Loading State 
   - Error State
   - Data Loaded State
most commonly used states in flutter.

```

abstract class WidgetSwitchCase {}

class LoadingWidgetCase extends WidgetSwitchCase {}

class ErrorWidgetCase extends WidgetSwitchCase {
  final String message;
  ErrorWidgetCase({required this.message});
}

class DataLoadedCase extends WidgetSwitchCase {
  List<int> data = List.generate(12, (index) => index);
}

```
Here's an explanation of each state class:

1. `LoadingWidgetCase`: This class represents the loading state of the widget. It is a subclass of `WidgetSwitchCase`, indicating that it is one of the possible cases handled by the `WidgetSwitchCase`. It doesn't have any additional properties or methods.

2. `ErrorWidgetCase`: This class represents the error state of the widget. It is also a subclass of `WidgetSwitchCase`. It has an additional property `message` of type `String` that stores the error message. When an instance of `ErrorWidgetCase` is used, the error message can be passed to it via the constructor.

3. `DataLoadedCase`: This class represents the state when data is successfully loaded. It is also a subclass of `WidgetSwitchCase`. It has an additional property `data` which is a `List<int>` holding some sample data. In this example, it generates a list of integers from 0 to 11 using the `List.generate` method.

> Note : You can define your own custom states.

## Usage:

It has very easy usage and also good readability

```
SwitchCaseWidget<WidgetSwitchCase>(
            activeState: switchCaseExample,
            stateBuilder: (WidgetSwitchCase? value) {
              if (value is LoadingWidgetCase) {
                return const CircularProgressIndicator();
              }
              if (value is ErrorWidgetCase) {
                return Text(
                  value.message,
                  style: const TextStyle(color: Colors.red, fontSize: 30),
                );
              }
              if (value is DataLoadedCase) {
                return Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: value.data
                        .map((e) => Text(
                              e.toString(),
                              style: const TextStyle(fontSize: 20),
                            ))
                        .toList(),
                  ),
                );
              }
              //default case
              return null;
            }),
```


OUTPUT


- Loading state:
  ![loading state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8lumy44uoigoae65pum.png)

- Error State

![Error State](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1acdkghb2k6p6fgvs19.png)

- Data loaded State


![data loaded state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89qk5jc2oav41j390mo3.png)


> Note: it is not going to reduce if-else condition but add more readability then normal if else in Flutter State widget.