Best Practices for Reactivity in Screen Flows (Beta)
Ensure your Lightning web components integrate well within the Flow runtime engine and work as expected for Screen Flow reactivity.
These sections describe state management with reactivity in Screen Flows, including:
- How LWC state management differs from Aura
- How state management works in the new LWC Flow Runtime
- State management and event best practices to follow when building LWCs for your screen flows
State management for Aura components and LWCs follow different paradigms. In Aura components,
<aura:attributes /> are viewed and modified by the component to which they belong, including external components. LWCs are designed to have a clear separation between internal and external states. Variables declared with
@api are intended to be modified only by the LWC’s parents. Variables without the
@api annotation and variables with
@track are considered internal states and can be changed within the LWC that defines them.
The Flow runtime adheres to LWC state management design principles. It works best when the LWC components that it renders do not modify their own
@api attributes. Instead, components request a change by firing
FlowAttributeChangeEvent, which is essential for several reasons.
- Components that allow their parents to control their
@apiproperties are more easily reused because they allow the application to control the state rather than the component’s own internal business logic.
- By firing attribute change events, the Flow runtime maintains an accurate picture of the component state. The Flow runtime can control inter-component interactions such as conditional field visibility, which is part of reactivity.
Using LWC linter rules is an excellent way to ensure that your component does not modify
@api properties. Set up a linter that uses LWC’s linter rules in your development environment, specifically ensuring that the setting is enforced.
To maintain consistent behavior between Flow Runtime versions, when a user clicks the Next or Finish button, the Flow Runtime collects values by extracting each custom LWC component’s current
@api attribute state before moving to the next screen or finishing the flow. This mechanism ensures that components that do not adhere to the prescribed design pattern continue to work in the latest Flow Runtime version. It is strongly recommended to avoid relying on this behavior.
Here is an example of a simple text input component that demonstrates firing
FlowAttributeChangeEvent instead of updating the LWC’s
The following example isn’t recommended.
FlowAttributeChangeEvent event provides LWCs the ability to inform the runtime of their current state. It is part of Flow Runtime’s state management mechanism. These events are meant to be fired whenever user interaction results in a modification that requires an update to an
FlowAttributeChangeEvent from the
Next, you can create an instance of the event.
FlowAttributeChangeEvent includes two arguments.
apiParameterName—The name of the API property to modify.
updatedValue—The updated value for the Flow attribute.
Pass a string to
For example, notice how
exampleApiParameterName is consistent in all 3 places:
Declare the attribute in the LWC’s
Declare the API property in the LWC’s
updatedValue to match the declared datatype in the
Declare the property as a Record:
Declare the property as a string:
Declare the property as a number:
Declare the property as a boolean:
After constructing a
FlowAttributeChangeEvent instance, you can fire the event using the
FlowAttributeChangeEvent examples and steer clear of problematic usages to reduce unexpected behaviors after a flow version upgrade. These best practices enable you to maintain your components more easily.
- Fire events in event handlers or in methods invoked within event handlers.
- Limit an event’s value parameter to the following datatypes: String, number, boolean, JSON (for record types).
- Ensure that the Flow datatype of the event’s value parameter matches the datatype of the LWC’s
- React to changes to
@apiproperties by using a get/set pattern where appropriate.
This example demonstrates using a getter and setter to count the updates with an
@api property vs. incrementing a counter before firing an attribute change event. Both patterns are valid, but they achieve slightly different results.
In this case,
this.changeCounter is incremented whenever the user enters a change in the text input and whenever the Flow Runtime determines that the
textValue property has changed. This approach accounts for component initialization and cross-component interactions via reactivity. Use an intermediate variable to render updates from the set method. In this example,
textValueToRender fills this role.
The following code example increments a counter before firing an attribute change event. This scenario doesn’t use the get/set pattern.
In this case,
this.changeCounter is incremented whenever the user inputs a change in the text input. The counter does not update when reactivity changes the value of this field.
Use annotationless or
@track properties to maintain a modifiable local component state.
The following example shows a color picker that presents the user with an input text box and some swatches. The color picker component returns
color to the flow, so only
color needs the
@api annotation. The
inputValue members are internal only and do not need any decorator.
Use a get method to combine multiple
@api properties together to construct a derived variable for the view.
Apply the same logic in the set method of every
@api property that contributes to a derived member variable needed for internal component state management, as in more complex scenarios than the previous example. This logic ensures that a change made to any contributing attribute causes the value to render correctly regardless of the order of the set attributes.
@api properties. Fire
FlowAttributeChangeEvent parameters after construction. By default,
FlowAttributeChangeEvent instances are composed and bubble.
FlowNavigationXxx events at the same time as it can lead to race conditions. There's never a guarantee that your Lightning web component has had time to render the updated values by the time the navigation process is started.
In addition to
FlowAttributeChangeEvent, your Lightning web components can fire navigation events to move between screens, pause, or finish flows. To work with navigation events, import these functions from
This snippet describes how to import and fire a navigation event. While the example uses
FlowNavigationNextEvent, the same structure holds for each of the available navigation targets.
Navigation events allow your Lightning web components to include additional control mechanisms. Fire navigation events when reacting to end-user interactions. Refer to these guidelines when using navigation events:
- Fire navigation events in event handlers (or in the method they invoke).
- Don’t fire navigation events outside of event handlers because it leads to a poor user experience.
- Don’t fire navigation events in lifecycle handlers like
- Place the logic for skipping screens in Flow Decision Nodes, not in the lifecycle of a screen.
- Don’t perform navigation in a dummy screen because it can lead to poor Flow performance.
- If you encounter a scenario where navigation must be done within the initialization phase of the screen because data isn’t yet available to Flow Decision Nodes, post a request for an upgrade in Idea Exchange