Written May 17, 2020. Tagged Elixir, Phoenix LiveView. There's no obvious way to save persistent session data in Phoenix LiveView. For example, I might implement a chat and want it to remember your username even if the page is reloaded, or you quit your browser and come back the next day. LiveView is stateful, but keeps its state in a process that quits when you leave the page. And since it only makes a single HTTP request initially to load the page (after that, it's all via WebSocket), we can't just set cookies or modify the Plug/Phoenix session like we're used to. I solved this by putting data in client-side I'm using LiveView 0.12.1. First, I modified mounted() { this.pushEvent("restore", { this.el.username.addEventListener("input", e => { let liveSocket = new LiveSocket("/live", Socket, { Then, in my LiveView module, I handle the "restore" event we pushed above: And finally, I add a And that's all we need! When the LiveView mounts, it receives a "restore" event containing any stored data, and updates its state. When the username changes in the form, the value is immediately put in localStorage, so it can be restored later. One downside of this solution is that the LiveView will first render without the stored data, so there will be a brief flash of an empty value (or whatever default value you set on Another solution I considered (UPDATE 2020-05-19: and later went with) would be to store a unique identifier in the session, make sure this is passed to the LiveView when it's mounted, then store the data under this identifier in a relational database or somewhere like Redis. The LiveView can then get or set data as it pleases. That is conceptually very similar to having a database-backed session store, but LiveView would access this store outside the HTTP request/response cycle. I didn't go this route simply because it seemed more complex, though it would avoid that brief flash of the default value, and avoid one round of re-rendering. Chris McCord, creator of LiveView, has shared example code for storing form data in URL params – this means data will survive reloads, but will not (by design) survive revisiting the site without those params. He also seems to suggest there may be a "stash" feature to come in LiveView, though I don't know how persistent that is intended to be. I'm new to LiveView and would love feedback and alternative solutions. Please write a comment below or on Twitter!localStorage
using LiveView hooks.Solution
app.js
to define a "StoreSettings" hook:let Hooks = {}
Hooks.StoreSettings = {
username: localStorage.getItem("username"),
})
localStorage.setItem("username", e.target.value)
})
},
}
params: {_csrf_token: csrfToken},
hooks: Hooks,
})def handle_event("restore", %{"username" => username}, socket) do
{:noreply, assign(socket, username: username)}
endphx-hook
attribute to the form so that this hook will actually run:<form phx-hook="StoreSettings">
<input type="text" name="username" value="<%= @username %>" />
</form>Discussion
mount
) before the value is restored.