Dart Tutorial

Flutter Lesson 7 of 83 2 min read

StatelessWidget in Flutter

Learn how to write a StatelessWidget in Flutter: the build method, constructor parameters, const constructors and when to use one.

On this page

A StatelessWidget has no data of its own that changes. What it shows depends only on the values passed to its constructor. Most widgets you write will be stateless.

The shape of a stateless widget #

import 'package:flutter/material.dart';

class Greeting extends StatelessWidget {
  const Greeting({super.key, required this.name, this.excited = false});

  final String name;
  final bool excited;

  @override
  Widget build(BuildContext context) {
    return Text(
      excited ? 'Hello, $name!' : 'Hello, $name.',
      style: const TextStyle(fontSize: 24),
    );
  }
}

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Greeting(name: 'Asha'),
              Greeting(name: 'Bimal', excited: true),
            ],
          ),
        ),
      ),
    ),
  );
}

The parts:

PartPurpose
extends StatelessWidgetMakes the class a widget
const Greeting({super.key, ...})A const constructor with named parameters. super.key passes the optional key to the parent class
final fieldsThe configuration. They never change after creation
buildReturns the widgets this one is made of

Why const matters #

Mark the constructor const, and write const where you use the widget whenever all its arguments are constants. Flutter can then reuse the same instance and skip rebuilding it. The linter reminds you when you forget.

const Greeting(name: 'Asha')      // created once, reused
Greeting(name: userName)          // not const: userName is only known at run time

Passing callbacks #

A stateless widget cannot change itself, but it can tell its parent that something happened by calling a function it was given.

import 'package:flutter/material.dart';

class QuantityButton extends StatelessWidget {
  const QuantityButton({super.key, required this.label, required this.onPressed});

  final String label;
  final VoidCallback onPressed;

  @override
  Widget build(BuildContext context) {
    return OutlinedButton(onPressed: onPressed, child: Text(label));
  }
}

VoidCallback is the type of a function with no parameters and no result. For a callback that passes a value, use ValueChanged<T>, for example ValueChanged<int> onChanged.

When does build run? #

  • When the widget first appears.
  • When its parent rebuilds and passes new values.
  • When something it depends on changes, such as the theme.

build can run many times a second, so keep it fast. Do not start network requests or heavy calculations inside it.

Stateless or stateful? #

Ask: does this widget need to remember something that changes while it is on screen?

  • No: StatelessWidget. A label, an avatar, a card that displays a product.
  • Yes: StatefulWidget. A checkbox, a form, an animation.

Start stateless. Converting later is one editor action.

Try it yourself #

Write a StatusBadge widget that takes a label and an isActive flag. Show the label in green when active and grey when not.

Practise in the playground Updated by Santosh Adhikari