Using setIn() to change a temp state variable

It's really useful to be able to create temp state variables and edit them using the setIn() method. However, we're finding the documentation about how to use it being somewhat limited. On the docs page for temporary state, it says:

state.setIn(path, value: any)
Sets the value of state.value at a specified location. The path variable accepts an array of keys/indexes to select. I.E. state.setIn( [ 0, "trout" ], {length_inches: 16 } ). The value will be set without destroying and recreating the other values of the state.

This same exact example with the trout is repeated verbatim on the Scripting Retool page and the components page.

What's not clear to me is exactly what goes in that array, and how it should map to the data structure. What makes the trout example particularly difficult is that I can't find any example of what the overall data structure that we're updating looks like. Obviously I can get it to work with specific examples, but what exactly that path is, and how it's constructed, is not clear to me. I was wondering if this setIn() method is something that's just generally understood by JS developers, but I couldn't find documentation for it elsewhere online.

In the apps I've been working on, we have a lot of temp state variables with all kinds of nested objects, arrays, arrays of objects, etc. etc. It's be nice to be able to know exactly how setIn() can be used to go the most directly to the nested level / location of choice, to write the cleanest and most efficient code.

a.) Do folks have insights regarding generally what can go in this destination array?
b.) Do Retool folks think you might be able to flesh out the documentation a little more for other users?

Thanks!

2 Likes

The first param of setIn provides an array of keys which resolve to the point within the data structure to update. For example, update the message object for "sun" on the first record in the data structure below with this call:

some_state.setIn([0, "sun"], new_message)

[
{
username: 123,
...
sun: {
message_id: "some id",
content: "some content"
...
}
mon: {
message_id: "some id",
content: "some content"
...
}
...
},
...
]

2 Likes

Thanks Chris. So, just to expand on this, you wrote:

The first param of setIn provides an array of keys which resolve to the point within the data structure to update.

Is it correct that:

1.) The array must always have two elements
2.) The first must be an array index
3.) The second must be an object name

What if my temp state variable is formatted differently? What if it's just an object?

Hey there @MarkR

The first parameter can be as long as you want, and it does not have a defined structure. The structure depends on the structure of your temporary state. See my example below of updating a nested value in an object:

As you can see, the path array is the name of keys which directs to the correct one to update. (in this case I wanted to update the value of key2 which is nested under the key named "a" and then under a key named "key"

4 Likes

This is brilliant, thanks a ton! Now one more bonus question - what if there were an array in the middle of those nested objects - could you reference an element of an array within an object within an array?

Like this?


2 Likes

Perfect, thanks so much for the demo!

No problem! If you have any other questions in the future, don't hesitate to reach out again!

1 Like

Mark, is there an easy way to delete inside a temporary state? I notice that .deleteIn() is not supported. At the moment, I'm running a .filter() on one of the nested arrays and then using .setIn() to overwrite the old array.

1 Like

@krasenhaus,

At this time there is not a .deleteIn() method, so you will need to use .setIn() as you have in order to delete items from temporary state. Would you mind posting this as a feature request so that other users who are interested can chime in on this?

1 Like

@krausenhaus and @mark,

Here is what I came up with for deleting a temp state array element:

let temp = Timers.value
temp.splice(i, 1)
Timers.setValue(temp)

I am not sure what the memory leak implications of this are. Do I keep creating new arrays doing this? Does the Garbage Collector handle these or do they stick around forever?

2 Likes

I'm assuming, unless I am misunderstanding how retool / javascript / computers work, that anything that you're not intentionally passing out of the query (like with a return statement) is going to be garbage collected automatically. Generally though, I would love more tips for preventing memory leaks in retool!

Hey Brad,

That is exactly how I would have done it, except maybe I would have skipped the assignment (no harm in doing it though!)

This should not cause a memory leak, as the garbage collector should clean things up for you.

FYI, I wasn't able to get setIn to work until I initialized the state variable to be an empty object.

Screen Shot 2021-12-21 at 9.25.23 AM