Reactivity
Reactivity
Reactivity is core concept within Slint. It allows the creation of complex dynamic user interfaces with a fraction of the code. The following examples will help you understand the basics of reactivity.
As the name suggests, Reactivity is all about parts of the user interface automatically updating or ‘reacting’ to changes. The above example looks simple, but when run it does several things:
- The
Rectangle
will follow the mouse around as you move it. - If you
click
anywhere theRectangle
will change color. - The
Text
elements will update their text to show the current position of theRectangle
.
The ‘magic’ here is built into the Slint language directly. There is no need to opt into this or define
specific stateful items. The Rectangle
will automatically updates because it’s x
and y
properties
are bound to the mouse-x
and mouse-y
properties of the TouchArea
element. This was done by giving
the TouchArea
a name to identify it ta
and then using the name in what Slint calls an expression
to track values. Its as simples as x: ta.mouse-x;
and y: ta.mouse-y;
. The mouse-x and mouse-y properties
are built into the TouchArea
and automatically update as the cursor moves over them.
The TouchArea
also has a pressed
property that is only true
when the cursor is pressed or clicked down.
So the ternary expression background: ta.pressed ? orange : white;
will change the background color of the Rectangle
to orange when ta.pressed
is true, or white when it isn’t.
Similarly the 2 text items are updating by tracking the rectangle’s x
and y
position.
Performance
From a performance perspective, Slint works out what properties are changed. It then finds all the expressions that depend on that value. These dependencies are then re-evaluated based on the new values and the UI will update.
The re-evaluation happens lazily when the property is queried.
Internally, a dependency is registered for any property accessed while evaluating a binding. When a property changes, the dependencies are notified and all dependent bindings are marked as dirty.
Property Expressions
Expressions can vary in complexity:
As the last example shows functions can be used as part of a property expression. This can be useful for when an expression is too complex to be readable or maintained as a single line.
Here the earlier example was updated to use a function to convert the length to an integer. This also truncates the x and y values to be more readable i.e. ‘4’ instead of ‘4.124488’.
Purity
For any reactive system to work well, evaluating a property shouldn’t change any observable state but the property itself. If this is the case, then the expression is “pure”, otherwise it’s said to have side-effects. Side-effects are problematic because it’s not always clear when they will happen: Lazy evaluation may change their order or affect whether they happen at all. In addition, changes to properties during their binding evaluation due to a side-effect may result in unexpected behavior.
For this reason, bindings in Slint must be pure. The Slint compiler enforces code in pure contexts to be free of side effects. Pure contexts include binding expressions, bodies of pure functions, and bodies of pure callback handlers. In such a context, it’s not allowed to change a property, or call a non-pure callback or function.
Annotate callbacks and public functions with the pure
keyword to make them
accessible from property bindings and other pure callbacks and functions.
The purity of private functions is automatically inferred. You may declare private functions explicitly “pure” to have the compiler enforce their purity.
Two-Way Bindings
Create two-way bindings between properties with the <=>
syntax. These properties will be linked
together and always contain the same value.
The right hand side of the <=>
must be a reference to a property of the same type.
The property type is optional with two-way bindings, it will be inferred if not specified.
The initial value of a linked property will be the value of the right hand side of the binding.
The two linked properties must be compatible in terms of input/output.
© 2025 SixtyFPS GmbH