View Source LiveData behaviour (live_data v0.1.0-alpha1)
LiveData makes it easy to synchronize a JSON data structure from the server to a client. Changes to the data structure over time is streamed as minimal diffs.
LiveData aims to provide a programming model similar to LiveView, but for arbitrary data structures instead of only HTML.
You write a render
function in your LiveData, which takes any assigns you
have set as an argument. Within the render
function you build the data
structure you want synchronized to the client. As you update the assigns
,
the LiveData library will take care of calling your render
function,
calculating diffs, and synchronizing to the client.
As with LiveView, your LiveData is just a normal process. The programming model should feel very familear if you have ever used LiveView before.
live-cycle
Live-cycle
Unlike with LiveView, the lifecycle of a LiveData is not tied closely to any given HTTP request.
In order to open a connection to a LiveData from the client, you would start out by making a connection to the LiveData socket endpoint.
On the LiveData socket connection, the client can then connect to any number of LiveDatas.
A LiveData ends when either:
- The client closes the LiveData socket connection. This will cause all LiveDatas that live on that socket to close.
- The client closes the individual LiveData. This will cause any other LiveDatas on the socket to remain open.
- The LiveData crashes or disconnects from the server side.
On a server-side crash or disconnect, it is up to the client to decide how to handle it. A common behaviour might be to reconnect.
keys
Keys
Using keys are very important if you want the LiveData library to generate efficient diffs for you.
Keys allow you to give the LiveData library a hint that it can identify a piece of data uniquely by a given identifier.
As a rule of thumb, you should use a key whenever are looping over and generating output from something dynamic.
example
Example
Say you have the following LiveData which returns a list of users:
deft render(assigns) do
for user <- assigns[:users] do
%{
id: user.id,
name: user.name,
[...]
}
end
end
Because LiveData has no way of knowing which parts of your data structure it can use as a comparison key when diffing, this would produce inefficient diffs.
The data for users can be uniquely identified by user.id
. We can inform
LiveData of that fact by doing the following:
deft render(assigns) do
for user <- assigns[:users] do
keyed user.id, %{
id: user.id,
name: user.name,
[...]
}
end
end
This will make LiveData produce efficient diffs whether the users in the list change order, any individual properties change, or other changes.
Link to this section Summary
Link to this section Types
@type rendered() :: any()
Link to this section Callbacks
@callback __tracked__render__(LiveData.Socket.assigns()) :: LiveData.Tracked.tree()
@callback handle_event(event :: any(), LiveData.Socket.t()) :: {:ok, LiveData.Socket.t()}
@callback handle_info(message :: any(), LiveData.Socket.t()) :: {:ok, LiveData.Socket.t()}
@callback mount(params :: any(), LiveData.Socket.t()) :: {:ok, LiveData.Socket.t()}
@callback render(LiveData.Socket.assigns()) :: rendered()