How to use temporary state setValue() when you need the value immediately? Awaiting does nothing

I'm trying to run the following script that sets a temporary state based on a selected table row, and then immediately uses that state for a REST Api. I'm not passing in the table data directly because it's possible for the user to still select rows in the background with the modal open (I'm still using this variable beyond the query), meaning I cannot rely on the selected row to be accurate, and there's no method to disable row selection.

On the first run when the capturedCompanyId temporary state is null, the deleteCompany is triggered while it's still null.

I tried awaiting the setValue command, that id nothing so then I tried then-ning it, and that still does nothing.

capturedCompanyId.setValue(Companies_Table.selectedRow.id).then(
  deleteCompany.trigger({
  additionalScope: {
    companyId: capturedCompanyId.value,
    dryRun: true
  },
   onSuccess:(data) => {
     console.log(data, 'onSuccess')
   },
   onFailure: (data) =>{
     console.log(data, 'onFailure')
     if (deleteCompany.data.data.error === "PROTECTED_ITEM")       {
       console.log('protected item')
     }
   },
}))

I'm not sure how we're supposed to use temporary states if we can't wait for their values to finish applying before using them. Are there any workarounds? I need to lock in the id property of the selected row once the user opens the modal.

Can you capture a reference with
const selectedCompanyId = Companies_Table.selectedRow.id
and then use that reference later in the script?

It's not that I need it later in this particular script, but rather I have a stepped container within this modal and I refer to the variable several times throughout the flow. It's just that within this script is where it fails. For now I'm just passing Companies_Table.selectedRow.id to the query's additional scope since it's obviously in no danger of changing that quickly, but that does mean I can still experience this race condition later down the line.

Hey @jtoronto! Just wanted to check in here as well. How's your app building going? Do you still have any questions I can help with here?

:wave: Just in case this helps as a reference point, we've posted a "Retool Tips & Tricks" walking through how to add a delay between queries.

Hey @jtoronto - one more suggestion for ya: await will work, but you'll also need to check on this setting on the advanced tab of the query Keep variable references inside the query in sync with your app

@kbn Hello, thanks for your notice. But it seem not work to text component when I checked it.

@AnsonHwang it should work if you add await at the front of line 1 in your example screenshot. Looks like you'll need to use both await and enable the checkbox for the Advanced setting Keep variable references inside the query in sync with your app. Let me know if that works for you!

@kbn Can you explain the purpose of the "Keep variable references inside the query in sync with your app" and what it does?

Happy to shed more light on this @haj! We also have a documentation request logged to elaborate on this in our official documentation - I've bumped that request internally. (Update: now included in docs Advanced query options | Retool Docs)

We can definitely share more context than what the tooltip describes:

If your query uses setValue on a component or variable, the "Keep variable references inside the query in sync with your app" setting will ensure that future references to that component or variable in the query have the updated value.

When not checked on, future references to the component or variable in the query will have the value from when the Javascript query was first triggered, instead of the updated value.

It's disabled by default for performance reasons, but we have an internal request to the product team to warn about this setting or make it more obvious that the setting should be toggled on if you're trying to use something like await tempState.setValue()

1 Like