Flutter - Stateless vs Stateful Widgets.
Tags: tutorial
Published: 2020-02-29 14:32:27


**_Have you been wondering about what exactly is the difference between a stateless and a stateful widget?_**

## Table of Contents
 1. [What are widgets?](#widgets)
 1. [Stateless Widgets](#stateless_widgets)
 1. [Stateful Widgets](#stateful_widgets)
 1. [Concept of External Data](#external_data)
 1. [Differences Between Stateless and Stateful Widgets](#differences)

## Widgets <a name="widgets"></a>
Widgets are the UI building blocks in Flutter. Everything that you see in a Flutter application is a widget. The entire Flutter Application is itself a widget.

Widgets are classified into two main types:

**1. Stateless Widgets**
**2. Stateful Widgets**

Let's dive deeper into both the types and later discuss the differences.

## Stateless Widgets <a name="stateless_widgets"></a>
Let's start by creating a new widget to get a better understanding of these concepts.

We will create a **Tips** Widget which will display a list of tips for programmers to view.


**tips.dart**
![Tips Stateless Widget Code](https://dev-to-uploads.s3.amazonaws.com/i/04hl6s8g3jpt9i9gkqzh.png)

### We have:
 - An array **tips** which contains the list of tips we would like to show the user.
 - A counter **tipIndex** which will track the tip which is to be shown.
 - A renderable **Text()** which will render the tip at the current **tipIndex**
 - A renderable **RaisedButton()** with the label **Next** which on clicked will render the next tip. Check out the logic of the onPressed function **changeTip()**.

### Let's embed this widget in our **main.dart** file.

**main.dart**
![main.dart](https://dev-to-uploads.s3.amazonaws.com/i/r75u5om65ai9gn0bfe17.png)

### Output
![Tips Stateless Output](https://dev-to-uploads.s3.amazonaws.com/i/5yubqkkw7m53i3gc730k.jpeg)

Now in this case after clicking the **Next** button, the **tipIndex** must increment and thus the next tip at the index position **1** should be rendered.

**BUT IT DOESN'T :(**

**WHY?**

Because our widget is a **stateless widget** as it extends the class **StatelessWidget**.

- Stateless Widgets do not have internal states as the name suggests.
- Stateless Widgets have no method by which the UI gets re-rendered whenever the internal values change.

_The only way a stateless widget can get re-rendered is by passing **EXTERNAL DATA** which we will talk about after understanding Stateful Widgets._

## Stateful Widgets <a name="stateful_widgets"></a>

These type of widgets do have their own internal states.

We will convert our stateless tips widget into a stateful one for more understanding.

**tips.dart**
![Tips Stateful Code](https://dev-to-uploads.s3.amazonaws.com/i/bp049dmi562ekd0lacem.png)

### Note the following to understand the conversion from stateless to stateful:

- The Tips Class now extends StatefulWidget class
- The entire logic of the tips app have been moved to _TipsState class which extends **State<Tips>** 
- **Tips** Class has a function **createState()** which returns the _TipState.

The above are the three essential changes required to convert a stateless widget to a stateful widget.

### Output 

![Tips Stateful Output 1](https://dev-to-uploads.s3.amazonaws.com/i/5yubqkkw7m53i3gc730k.jpeg)
After Clicking the next button
![Tips Stateful Output 2](https://dev-to-uploads.s3.amazonaws.com/i/5mwgmzfbol8xgg1ustbv.jpeg)

_Now this is the output which we needed and the main reason it works is because of **setState()** method which is applied in **changeTip()** function_

![setState Function](https://dev-to-uploads.s3.amazonaws.com/i/ih1ctvfb0qhwb2qyfpx9.png)

**setState()** is a special function only available in Stateful Widgets which updates the state of the widget and re-renders the components that are affected by the change in state.

We specify the state which is to be updated in setState() function **[we incremented tipIndex]**

In our case, only the **Text()** which displays the tip is re-rendered because only that widget is associated with the change in **tipIndex**.

Now, let's discuss how **Stateless Widgets** can get re-rendered using External Data.

## Concept Of External Data <a name="external_data"></a>

**EXTERNAL DATA** is the data provided to a widget through its constructor.

Now it's time we split our **Tips** Widget into two parts:
- TipsView **(Just The Widget)**
- Tips **(Top Level Logic)**


**TipsView** will just consist of renderable components **Text() and RaisedButton()** [Note that this is a stateless widget]

**Tips** will contain the top-level logic. The list of tips and the functions to handle the state change will be in this part. [This is a stateful widget]


This concept is similar to **LIFTING THE STATE UP** used in web frameworks.

Let us understand how a stateless widget can get-rendered.

**tips_view.dart**
![TipsView Code](https://dev-to-uploads.s3.amazonaws.com/i/2fzmaczzlzdbsgqv4nkr.png)

TipsView is a stateless widget which has a constructor which takes 3 parameters **tip, changeTip and tipIndex** 

- tip **(The Tip To Be Displayed)**
- changeTip **(A pointer to the function which changes the tip)**
- tipIndex **(The Current Tip Index)**


**tips.dart**
![Tips Code](https://dev-to-uploads.s3.amazonaws.com/i/rv45vlu9zpgdeh0cnk95.png)

This is the top-level widget which renders the TipsView and **passes down the parameters tip, tipIndex and pointer to the changeTip function**.

### FLOW 

1. The build method of Tips will render the TipsView with the first tip.
1. When **Next** button inside the TipsView will be pressed, the changeTip function **residing in Tips** will be called since it's pointer is passed down to TipsView.
1. The tipIndex will get incremented and then the **entire TipsView widget will be re-rendered** with changed parameters.

Even after splitting the application it will still have the same functional result.

**Note that in this case the entire stateless widget including Text() and RaisedButton() will be re-rendered and not just the Text()**

So this is the use-case which shows re-rendering of stateless widgets.

## Differences Between Stateless and Stateful Widgets <a name="differences"></a>

1. Stateless widgets have no method to re-render themselves if **INTERNAL DATA** changes.
1. Stateless widgets can only be re-rendered when **EXTERNAL DATA** changes.
1. If a stateless widget is re-rendered then the entire widget is re-rendered.
1. Stateful widgets can be re-rendered when **INTERNAL as well as EXTERNAL** changes.
1. The **setState()** method in Stateful widgets re-render components only associated with the change in state. It does not re-render the entire widget but only the necessary parts of it.

## Thank you for reading this article 💖.