Liveview and database queries, does this run once or twice?

Hi all,

quick one here.
In the mount function I make a db query to get a record.

def mount(...
  item = query_db_and_get_an_item()
  %{:ok, assign(socket, item: item)}
end

Does it run the query twice? One when it’s not connected and one when it is

OR

Does it run only once because I assign the item in the socket and LV see it’s not changed?

Just a small clarification because unfortunately I am working on a project alone and I have no one to phisically ask :sob:

It will (usually) run twice. Once when the http request renders the LV statically and then each time the websocket connection starts, which could also happen multiple times if the connection drops intermittently.

Ah!
Is that an accepted pattern or should I avoid run the query multiple times?

Thank you

If you need the data in both those usecases you need to query it. If not you can use connected?(socket) to differenciate between the two.

I need the data.
I will execute the query only if the view is not stateful.

Thank you

That sounds like you don’t need the data in the static render then.

Umm I need the data in the static render, it’s a detail view for an item from the database.
Am I off track here?

A sorry missed a “not” in your sentence. You can make things work with loading data only in the static view, but you’ll need to make sure the stateful render doesn’t replace the existing data.

2 Likes

I am doing this in the mount function:

def mount(...
  item = if connected?(socket) do
    socket.assigns.item
  else
    query_db_and_get_an_item()
  end

  %{:ok, assign(socket, item: item)}
end

Which in my head sounds like first time take the item from the database, next time take it from the socket, but I get this error:

** (KeyError) key :item not found in: .... 

What am I doing wrong here?

There is no data – besides the session – being shared between the static render and the connected renders. You either build the system in a way to not need the assign in the connected render or you need to query the data again.

1 Like

I see,
is there any best practice to follow or is it a developer decision (to query the db sooner or later)?

I feel like I need some literature or example project to see what’s the static and connected distinction can be used for…

Thank you

As I see it, if its cheap to fetch (simple query) then fetch twice.
If not, consider one or more of:
Fetching just a part of the dataset
Cache the query
Only query when connected and not in static.

A key thing missing in this thread is that if you use push_redirect and the other navigation helpers then the websocket connection is maintained. This means that you only do the double render on at the first moment the user goes to the site. After that it can simply do a single render.

2 Likes

Here’s an example from an older thread if you would rather query the db only after connected?(socket) == true. The entire thread is well worth the read and explains the context behind LiveView’s lifecycle architecture/design.

Enlightening. Thank you