Migration to Flutter Guide
Discover our battle-tested 21-step framework for a smooth and successful migration to Flutter!
Home
Glossary

Conditional rendering in Flutter

What is conditional rendering in Flutter?

Conditional rendering in Flutter means building different widgets depending on a condition, such as application state, user input, or data availability. Instead of hiding UI elements, Flutter decides which widgets exist in the widget tree during the build() phase.

Because Flutter UI is written in pure Dart, conditional rendering uses standard Dart control flow rather than templates.

Why does it matter in Flutter app development?

Conditional rendering affects:

  • widget tree size
  • rebuild cost
  • state lifecycle
  • UI correctness

Because Flutter rebuilds widgets frequently, choosing the right conditional pattern improves performance and prevents subtle UI bugs.

How does conditional rendering work?

Flutter relies on Dart language features:

  • if statements inside widget lists (children: [])
  • ternary operator (condition ? A : B)
  • early return statements in build()

Example with collection if (recommended):

Column(
  children: [
    const Text('Profile'),
    if (isAdmin) const Icon(Icons.shield),
  ],
);

Example with ternary operator (single slot):

child: isLoading
    ? const CircularProgressIndicator()
    : const SizedBox.shrink(),

When to use conditional rendering?

Use it when:

  • Showing loading, error, or empty states.
  • Rendering UI based on permissions or authentication.
  • Reacting to nullable data.
  • Adapting UI to platform or screen size.

For large UI differences, returning early from build() keeps code readable:

if (error != null) {
  return ErrorView(error!);
}

When not to use conditional rendering?

Avoid conditional rendering when you want to temporarily hide UI but keep its state.

Using if removes the widget from the tree, which resets state such as:

  • text in a TextField
  • scroll position in a list

In those cases, prefer Visibility(maintainState: true) or Offstage.

Key characteristics

  • Widgets are created or removed during build.
  • Conditions run on every rebuild.
  • Strongly tied to Dart null safety and type promotion.

Common mistakes

Several issues appear frequently:

  • Deeply nested ternary operators that reduce readability.
  • Using placeholder widgets instead of collection if in lists.
  • Forgetting that if removes widget state.
  • Misusing empty widgets in the wrong context.

SizedBox.shrink(): when to use it

SizedBox.shrink() is not inherently bad, but context matters.

  • In widget lists (children:):
    Prefer if to add or remove widgets. Avoid returning empty widgets.
  • In single slots (child:, builder:):
    You must return something. SizedBox.shrink() is the correct and lightweight choice, better than Container().

Best practices

To keep conditional rendering clean:

  • use collection if in lists whenever possible
  • use ternary operators only for simple, single-slot decisions
  • extract complex conditions into helper methods or local variables
  • remember that removing a widget also removes its state

Used correctly, conditional rendering keeps Flutter UIs predictable, performant, and easy to maintain.

Learn more

Flutter architecture by LeanCode

Feature-Based Flutter App Architecture - LeanCode

Read about the LeanCode approach to Flutter architecture. We highlight some of the design decisions that should be made when developing a feature in mobile apps. This includes our approach to dependency injection, state management, widget lifecycle, and data fetching.

Social Media Activity Feed with Stream

Implementing Social Media Activity Feed with Stream

In a recent project, we embarked on the exciting task of enhancing an existing app with dynamic social media elements. Choosing Stream as our ally, we navigated through challenges and came up with strategies that helped us overcome them, resulting in the successful delivery of a news feed feature. Read our complex article.