Newbie Guide: Using States & WF Sequencing

As a resident forum stalker that spends way too much time in the forums, I’ve noticed an influx of new users. I have a little bit of extra time and the mood so I’ll share a primer on States.

State Management
Managing states in Bubble can be a mess since there’s no Master list for states in your page. Use dedicated groups for different types of states. Here’s an example of how I will setup a page:

image

I have dedicated groups storing different states all starting with #. Why? Cause it’s easy to press shift+3. In the same example you will see #Header v3 which is a reusable element and does contain its own states, hence the #.

This makes storing and searching for states a whole lot easier.

Use States To Store Loaded Data
All new Bubblers should make it a practice to store Data into states to help you manage Data better.

  1. You can use one State as a Data Source for multiple elements & conditionals.
  2. Reduce WU usage by removing Real-time Search costs where you don’t need it.
  3. Better control of Data (explained in the next section)
  4. Create a better User Experience
  5. Repeating Groups work better with loaded data

Workflow Management: Understanding Action Sequence
New Bubblers will always get confused about how workflow actions actually run. I won’t dive into detail about that here as there are plenty of other threads about this. Here are some important bits you need to know:

  • Client-side actions follow their sequences (setting states, showing/hiding elements, Pauses, Custom Events etc)
  • In a workflow, Schedule API actions will always run first regardless of where they are in your workflow unless…
  • Conditions and values that depend on values from a previous action will wait until that value is available. So while you can make Schedule API actions follow your workflow sequence, it will immediately trigger once it gets its value from the parent action regardless of where it is (based off my experience so far).

Workflow Management: Setting States and Custom Events
Now you know a little more about action sequences and why you should store data into States, you are now able to plan better control of your data using States and Custom Events.

Setting States and Custom Events are client-side actions and will always run in sequence. So do Pauses. Which makes the below work as intended.
image

Schedule Custom Event actions also follow this sequence. See this example:


So the above sets a state then schedules the Custom Action to run after .5 seconds then the pause starts and ends then sets a state.

2 things to learn from this is:

  1. A client-side action does wait for the previous action to execute. Eg. Step 4 only triggers after Step 3 completes updating its state
  2. The Custom Action runs .5 seconds from the point it was triggered in the sequence so it’s actions can run simultaneously. Yes, Bubble does allow parallel workflows.

Improve User Experience: Preload Data
You can use States to preload Data. Know that you can use multiple lists as your RG’s data source as seen below
image

For example in a Repeating Group that you may want to show 100 pieces of Data. Your user isn’t going to need to see all 100 immediately. You can load 10 on a page load and then schedule a custom event to load the other 90.

In this example what I will do is load the first 10 into one state on page load and then schedule a custom event to load the other 90 into another state.

Improve User Experience: Use Loading States
Use states to keep track of when the page is loading data and when that data is complete:
image

Having a state that tracks data load means you can create loading elements to improve your user experience. Users don’t mind waiting, what they do mind is not knowing if something is happening or not.

Here’s a simple method.


In my custom event, I start by setting the load state to yes. This shows my loading element.


Then I load the Data into my data state.

Now to there are 2 ways to update the loading state:


I can change the loading state immediately after (or after a pause action) I load the Data into my data state since it is supposed to run only after the data state is filled

Alternatively, I can use a Do When event to check that the right number of data is loaded into the data state using another state that counts the expected number of data. This does require an additional state, extra actions and the Do When event.

Easiest method to do this is would actually be with plugins that can watch for when an expression’s value changes.

Things To Watch Out For
Using States and Custom Actions are the most reliable way to control your data and workflows but because Bubbling means working with both client and server, there will be cases where you think it might work, but it actually doesn’t, but actually it does. Get what I mean?

So here are some additional tips and some things I will always take into account.

Storing Extremely Large Data Into States
You might break the sequence if the Data takes too long to load and store into a State. I’m talking about loading thousands of Things with multiple fields. As a general rule avoid this. If you need to load very large amounts of data you can always do it in parts using Custom Actions. I personally have never needed to do this since I use a lot of satellite datatypes.

You Can Use States To Watch Data Changes and Trigger Workflows
Example; You can setup a state that watch the difference in count between the loaded data (stored in one state) and the real-time search count of the same Dataset (stored in an input element). Use the difference to setup Do When logic.

Though I would highly recommend using plugins for this. There’s Floppy and Listopia to name the few I know of.

The :count Operator

image
This costs way less WU than
image

Last But Not Least: RTFM
Click on that Question Mark icon to open the Help Center
image

11 Likes

I’m aware of how most of these things work but this is REALLY a great idea! I just usually stack all of the states in the outermost parent container — making it a bit cluttered. Will keep this in mind, thanks!

1 Like

I used to do that but then I often got completely lost on what state did what. I tried adding the state type in the name but then they got way too long… Eventually settled into this and it works best for me. I don’t think I can do it any other way, even if Bubble created some new state masterlist thingymabob.

3 Likes

I like this idea. I always just put all my states onto the page or the reusable so I remember exactly where states are. I usually don’t use states too much though, so I don’t always get lost, but if I were to start implementing more uses of states this may be helpful to stay organized.

I personally think it is better to make use of a plugin, although my go to is no longer karma ware available, the developer did spin it off into a paid plugin of theirs, but there may be some free ones out there that do the same thing. This helps to reduce the need to run actions to load data, and eliminates the need for states to determine if the data is loaded or not as the plugin (if well built) will provide for those types of values already.

Could you provide some evidence provided by Bubble that confirms this? I understand that all actions are triggered just after the previous action is triggered, so action 2 is triggered after action 1 is triggered and doesn’t wait until action 1 is complete, and I’ve never heard that there is a difference between the type of actions (ie: client side versus server side). I see this when in step by step mode trying to investigate the setting of a state and it will not follow the order necessarily (may be the known limitation with step by step that causes this).

I try to avoid pauses at all costs as they are arbitrarily set and not a fool proof method for ensuring the previous step was completed before the pause is finished, nor can they pause by dynamically tied to the time it takes to load some kind of data.

What exactly are you doing in the set state list of text #states in step 1 that requires the pause in step 2 that leads to the set state list of text #states in step 3…looks confusing from the screen shot without knowing what kind of data values are set in step 1 and step 3 and if the custom state in step 1 is the same or not of the custom state in step 3…also, if they are the same, and setting a custom state triggers in sequence (which I suppose you mean you can simply rely on them triggering after the previous step triggered, but not necessarily after the previous step has finished its operation).

For me, a better approach that is more likely to result in consistency and relies only on the time it takes for the set state of step 1 takes to complete is to put the set state from step 1 into a custom trigger (because all actions in a custom trigger will complete prior to actions in the other series where the custom trigger is triggered from the follow the custom trigger in a sequence would be triggered)…the adjustment would be that step 1 is a custom trigger that has an action to set your state and step 2 would be another custom trigger that sets your state in step 3.

Again, I’d like proof of this, and also an explanation of why you require a pause between two client side actions in your screen shot of step 1 set state, step 2 pause and step 3 set state…if client side actions wait for the previous to step to execute, why would you need a puase?

Pagination is another great way to get better UX in terms of load speed…can set up to give user control over how many to show per page, but on default setting show 12 as that is divisible by 4, 3, 2 and 1 (all column numbers likely to be seen as a page is responsive)…all other options of the number of items to show per page should be multiples of 12, such as 24, 48 and 96

I agree…some plugins provide the values already of ‘is loading’ or ‘is loaded’…I wish Bubble would fix how the repeating group operators work for that.

Very good method to reduce amount of load time when not all data fields are necessary, as well as to reduce WUs…can’t wait for Bubble to implement the needed feature of allowing us to return only the fields we want.

You should explain this a bit more, or link out to the forum thread that was originally posted explaining this…it is important for others to understand the differences and what each would be used for.

Thanks for sharing some tips based on how you build. Always great to hear different perspectives for achieving the same end results.

3 Likes

Most definitely. Since ListShifter is no longer karmaware, Floppy is the very first purchase I’ll make for each new app.

In the example it’s just part of a test. I only use pauses for visual elements. I don’t like it when my loading element flashes for like 300ms and purposefully add an additional pause to make it show for a second or a half.

There are a number of posts about sequencing, but I’ll quote @keith since his explanations are always in-depth. He goes into even more detail as the thread goes on:

Here’s some general info from the manual:

General rules about how workflows run:

  • Frontend workflow actions run in order but the next action does not wait on the previous action to be complete before triggering.

  • Backend workflows are triggered as soon as the workflow is triggered, independently from steps. For example, a “Schedule API Workflow’” action will be triggered as soon as the workflow is triggered even if it is placed last in the workflow action sequence.

  • Custom events run in sequence, not parallel. If Workflow 1 triggers a custom event that starts Workflow 2, Workflow 2 will complete before the remaining actions in Workflow 1 run.

  • Searches aren’t always immediately updated with new data. So if you create a new item, and then try to retrieve it via search, it may or may not work; you should not rely on this.

    • Retrieving a thing from “result of step X” where step X is the “Create…” step should always be safe.

I have a small test page for state sequencing but it reflects how I set up complex workflows in my apps:
coffeehat-sandbox | Bubble Editor

Just to add as a reference to the types of client-side actions I refer to. From the manual:

Client-side processing
Many actions that you run in your app do not need to be sent to the server to be completed – indeed, many of them can’t be processed on the server since they refer to things happening locally on your user’s device.
For example, events, actions and conditions such as the ones listed below will in many cases be completed locally:

  1. Navigating between pages by use of the Go to page action.
  2. Displaying or hiding elements.
  3. Changing the appearance or styling of elements (colors, fonts, etc.).
  4. Validating user input in forms before submitting the data to the Bubble server.
  5. Performing calculations or manipulating data locally.
  6. Saving custom states with local content (such as user input)
  7. Triggering animations or visual effects.
  8. Running custom JavaScript code within the browser.
  9. Do when condition is true where the condition does not happens server-side
  10. Do every X seconds

Here’s the link to the thread for those looking:

Thanks for the peer review!

I should remind everyone (not singling you out) that Bubble has its quirks. Like search :count vs search:first item is empty, the way search:filtered works, and how current date/time works in a workflow (it will use the current date/time that the event was triggered).

1 Like

I agree…when I have a processing screen with lottie files, I try to tie the visibility of that to the lottie file duration rather than just the time it takes to process the data.

Thanks for sharing that.

1 Like

@ihsanzainal84 thank you for this.

I’m using Floppy to store lists of data and using session storage to save on the number of times i need to actually hit the db between a user coming in and out of the page. Really great.

One thing that hasn’t been consistent is the “Do When” conditional. Maybe my condition isn’t good.

I have a group that holds the :last item of a data type and the Do When simply says if "Floppy List doesn’t contain “group:last item” then "add “Group:last item to Floppy list”

Have you ever experienced this? Should I be using a count to determine when to update my Floppy list or the Custom State?

What do you do? Thanks for your feedback!

Well… I should’ve read the manual. “Do when” was set to only once. It should have been every time. Hit the manual on Do When and it’s the first point. Thanks again! This post is about to save me many WUs

[quote=“ihsanzainal84, post:1, topic:279221”]
Last But Not Least: RTFM
Click on that Question Mark icon to open the Help Center
image

1 Like