Docs

Documentation versions (currently viewingVaadin 25.1 (pre-release))

Managing UI State

Introduction to managing reactive UI state with signals in Vaadin Flow.

UI state is data that affects what users see and interact with - things like form values, toggle states, and dynamic content. Vaadin Flow provides signals for managing this state reactively.

Note
Preview Feature

This is a preview version of Signals. You need to enable it with the feature flag com.vaadin.experimental.flowFullstackSignals. Preview versions may lack some planned features, and breaking changes may be introduced in any Vaadin version. We encourage you to try it out and provide feedback to help us improve it.

Reactive State with Signals

A signal holds a value. When the value changes, any UI bound to that signal updates automatically:

Source code
Java
import com.vaadin.signals.local.ValueSignal;

public class Counter extends VerticalLayout {
    private final ValueSignal<Integer> count = new ValueSignal<>(0);

    public Counter() {
        Button button = new Button();
        button.addClickListener(click -> count.update(c -> c + 1));

        // Text updates automatically when count changes
        button.bindText(count.map(c -> "Clicked " + c + " times"));

        add(button);
    }
}

Without signals, you would need to manually call button.setText() every time the count changes. With signals, you declare the relationship once and the framework handles the updates.

Benefits

Signals provide several advantages over manual state management:

Automatic updates

When state changes, all dependent UI updates automatically - no manual synchronization needed.

Consistency

Multiple components bound to the same signal always show consistent data.

Thread safety

Signals handle UI thread synchronization internally, so you can update them from any thread.

Alternative: Setters and Listeners

Signals are not mandatory. You can also manage UI state manually using component setters and event listeners:

Source code
Java
public class Counter extends VerticalLayout {
    private int count = 0;

    public Counter() {
        Button button = new Button("Clicked 0 times");
        button.addClickListener(click -> {
            count++;
            button.setText("Clicked " + count + " times");
        });
        add(button);
    }
}

This approach works well for simple cases. Signals become more valuable as complexity grows - when multiple components depend on the same state, or when state changes need to trigger updates across different parts of the UI.

Learn More

This introduction covers the basics. For comprehensive documentation on signals, including shared state across users, computed values, and transactions, see UI State.