ELI5: What are states initialization and circular dependencies?

I’ve been having a problem with a plug-in I’m trying to build and I’m rereading the manual, rewatching @eli ’s tutorial, and generally so deep in StackOverflow I’m earning badges.

But I don’t grasp this thing. The description text makes me question my questionable intellect because I don’t get it.

Could some explain this to me like I’m 5? When do I have to use it? How do I use it?

It’s probably easier to explain how to generate a circular dependency error:

  • create a plugin element with a filed of type text, let’s call it “textinput”
  • add a state of type text, let’s call it “textoutput”
  • let’s initialize “textoutput”
    image
  • now in the app editor let’s assign a value to “textinput” that reference the element state
    image
  • go to preview and watch your error :slight_smile:

It looks complicated but it’s the equivalent of this javascript code
image
it’s just made in 2 steps between the plugin code and the editor

You are literally telling bubble to inizialite the state “textoutput” with the value of the state “textoutput”.

A solution is to initialize the state in the initialize function where you don’t have the properties and you can only initialize the state to a static value. Then publish the state value in the update function.
image
image

I hope it’s more clear now

Cheers

Mariano

3 Likes

Duuude!!! :bowing_man:
Consider myself educated! Wow, thanks! I get it now.

1 Like

Should I always initialize any value that I plan on using with publishState?

Hey @rico.trevisan, are you actually running into the issue of the issue checker throwing the circular dependency error for your plugin?

If not, don’t worry about this somewhat confusing note. (Though @dorilama provides an example of how you might cause a circular dependency error.)

But, what this note is referring to is the two different ways to initialize the value of an exposed state (we’ll get to those in a second).

An exposed state is how the plugin communicates values back to Bubble. For example, in List Shifter, I expose a ton of different states like “List Shifter’s Original List”, “List Shifter’s Shifted List”, “Initialized”, etc. Those are “exposed states”. (In my videos and documentation, I more often refer to those as the plugins “outputs” – because that’s essentially what they are and feel “exposed states” is overly verbose.)

In the plugin editor, they are defined here:

One does not have to provide an initial value for an exposed state. In some cases, we may be fine with having them be empty/null and there’s no point in initializing them further.

But in some cases, we might want to populate them at initilization time. And there are two ways to do this. The “default” way (but I would say this is not the preferred way) is that every exposed state that you define has its own “Code state initialization” block in the editor. Those appear here:

And so, as you can see in the example, we can define a function whose return value becomes the initial value for the state, as in this simple example from a test plugin.

But this way of initializing your states is pretty much madness, as why separate your code all over the place in those dumb little boxes?

ALSO, Bubble did at one time actually break the processing of the “code state initialization” functions and I presume that could occur again. This method of initialization seems to have been provided to make very simple plugins even simpler to create. An example would be the early versions of Browser Timezone & Locale, which just exposes things like the user’s timezone. And in that first version it just looks like this:

But we can instead initialize those outputs using instance.publishState() like so (this is the current version of Browser Timezone & Locale):

This, to my mind is a much better way to do things. Most of my code for a plugin will be in the initialize function which defines everything we need to do and executes itself. Then, in sections like Code Actions, I just reference the already defined action code. And we don’t need to fuss with the Code state initialization sections at all.

For an example of this, look at my Fielder plugin. This is generally how more sophisticated plugin devs do their code.

4 Likes

I usually publish all the states in the update function just because I have everything in one place and that works better for the way I reason about it.

1 Like

Thanks, Keith!

No, I’m not getting circular reference warnings. I was facing a couple of problems and my troubleshooting <airquotes> technique </airquotes> I was to ogre around the plugin builder trying all the buttons.


Wow, so you build your entire plugin in the initialize and then just pass the properties to that function afterwards. Noice.

Also, I appreciate how you write your code with the native Bubble objects: instance.data.whatever. Is it a style choice or are there some performance gains?


Let me blabber on about my problems, maybe you guys can spot improvements. Context: it is a text editor plugin. The text editor works when it’s alone on the page and has only 1 source of content. It fails when it is in a popup and the source changes often. It will load with the content from the previous popup or it won’t load any content or it will let me type, but then erase everything I just typed.

Any ideas?

1 Like

So presumably your editor uses some library and you’ve defined that script in the Headers section? If you’ve done this correctly your script will be loaded in the page and available even if your element is in a popup.

If not, that’s what’s causing your element not to work in a popup.

I’m not sure what you mean by this, though?:

In answer to your question:

Well, Bubble passes the instance object to our functions everywhere. And it provides the data object property on instance as a place to store values we need to access and pass between in our various functions. So that’s where I put them.

We could also make some other object on instance (e.g., instance.d = {})as a place to pass such values, but data is already there.

I’m almost there. Thanks for rubber ducking with me. I was not loading the content into a variable on the update function.


@keith, what I meant with my question if it was a style choice, is that I see a lot of plugins where people will create a bunch of variables like:

let thing = properties.thing;
const objectA = instance.data.objectA;

I thought it was a way to make your code more readable and save on keystrokes, but I just learned my lesson: this is how Bubble loads your data.

It happened!

But now I know how to fix it Danke!

way to go! :slight_smile:

1 Like

Is there a way to add conditions in the styles tab?

do you mean adding a condition in the style tab from the plugin? Or maybe adding oprions in the dropdown of the style tab?

My written messages quality is super low, sorry for not being clear. I mean the first: adding conditions in the style tab from the plugin.

I just went back and realized that I could change the type of element (I had completely forgot that option).

Just went back through the editor and re-read all the options and realized that there was a “in style” checkbox. Note to self: that only shows if it’s NOT set as a dynamic value.

It shows the option (2), but not in the “when…” (1). Pity.


What do you experienced Bubblers think about boolean fields:

  1. better as checkboxes
  2. better as dynamic yes/no

Looking at Keith’s Fielder and ListShifter it’s the latter all the way.

It depends on how you want to update thes as user:

  • checkbox : you need a condition to update it
  • dynamic value: set up an expression and the value updates automatically because is reactive
1 Like

I typically make all of my properties dynamic, @rico.trevisan.

1 Like