_toni

_toni

LiveView. Implementing a Shopping Cart Component. How to load state from localStorage and forward it to Components

Hello :wave:

I’m trying to implement something similar to a shopping cart.
I’ve got two LV.

  • Page LV
  • SecondPage LV

They both need to render the CartComponent (in the future a full-featured cart, right now only a %{ total: X}.
The component is stateful and handles the events (see component-click event within CartComponent).

I originally followed this very interesting thread regarding not un-mounting components upon a LV change via routing, however I couldn’t make the proposed solution work. Regardless I’m giving it a try via localStorage instead, so I figure that’s a different solution.
My goal is by steps:

  1. User lands in either of the LVs (which make use of CartComponent)
  2. JS hooks load localStorage.shoppingCart --> forward it to LV
  3. LV receives the socketParams and forwards it to the CartComponent whose update re-renders with new value.
  4. Whatever new event in the cart logic --> CartComponent handles it and it is appropriately updated.

The problem I’m encountering is with the first render of all. Something like this happens.

  1. User lands in PageLive --> renders CartComponent with empty shoppingCart
  2. Second time PageLive is mounted when the connected?(socket) is true --> receives new shoppingCart from JS hook.
  3. CartComponent's update does fire and receives the updated shoppingCart post-socket connected.
  4. CartComponent's UI render does not update
  5. Manually try to fire a component-click event --> CartComponent handles and UI is properly updated.

This is the very test repo i’m running


Am I missing something to make that first update re-render?

Thanks!

Marked As Solved

outlog

outlog

your example is a bit broken - the js breaks, when localstorage is empty fix:
shoppingCart: JSON.parse(localStorage.shoppingCart || null) || "{}",

now when decoding the json you’ll get a map - not a struct…
so change the render in cartcomponent to Map.get(assigns.shoppingCart, "total")

notice “total” vs :total

likewise when you update do it in a map:

    shoppingCart = %{
      "total" => Enum.random(10..1000)
    }

this code is broken elixir

shoppingCart = %{}

if connected?(socket) do
  IO.puts("Component connected")
  shoppingCart = Jason.decode!(Map.get(assigns.socketParams, "shoppingCart"))
end

do:

shoppingCart = if connected?(socket) do
  IO.puts("Component connected")
  Jason.decode!(Map.get(assigns.socketParams, "shoppingCart"))
else
  %{}
end

also wrap your value in a html element (liveview needs this)

<div><%= Map.get(assigns.shoppingCart,"total") %></div>

then it should work…

ps: made a fork with the fixes if anybody finds this thread… https://github.com/petermm/component-test

Also Liked

Exadra37

Exadra37

This is client side storage, and you cannot trust it, therefore I am not fan of using the browser local storage for storing data.

So my advice is for you to figure out how you can make it work properly via backend, and not not via browser local storage.

Sorry not be able to help you with your way, but I am also new to Live View.

_toni

_toni

Thank you @outlog your answer helped me debug the specific problem communicating
LiveView -> LiveComponent :slightly_smiling_face:

In parallel I also tried to solve a tangential problem here, which tries to have a common source of truth for all LVs that will consume the shoppingCart (basically I wanted to keep the localStorage-resumed shoppingCart in memory so every newly mounted LV could consume it without having to resume form localStorage again). Unfortunately I couldn’t land it in the way I intended, but I think I’m overcomplicating things so I’ll pivot my approach.
Regardless that’s a different story.

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

We're in Beta

About us Mission Statement