chrisdel101
Within a single parent live view I want to move from one component back to another via a shared parent. I need a newly set socket state to prevail. I’m using push_patch. I thought the reload: true option was what I needed, but adding it has no effect. ![]()
Why not put it in the query params? Since it’s a list and/or a changeset. Trying to do it causes errors.
Seems like a common enough process that I must be missing something. Also misunderstanding what the “patch” being pushed is. How can I make this work the right way?
So I add my new data to the socket. This is the workflow:
- CHILD: add new data to the socket in child component
- CHILD: redirects back to the parent component
Index. - PARENT: Call received.
mountis skipped and onlyhandle_paramsis called - PARENT: socket is examined and new data is not present
Code
# inside CHILD component I want to switch, but it passes through the parent first, without my new data
socket = # assign the data
socket
|> assign(:existing_users, existing_users)
|> assign(:user_changeset, user_changeset)
{:noreply,
socket # go back to parent now
|> push_patch(to: Routes.user_index_path(socket, :display)}
# PARENT component - data is not persisting that I just added
def handle_params(params, _url, socket) do
IO.inspect(socket.assigns.user_changeset) -> nil
IO.inspect(socket.assigns.existing_users) -> nil
# Data from original `mount` is still available only
end
#
Note: The app is only 6 months old but it looks it’s using liveView version 17.5
Edit: If I call handle_info on the parent component manually inside child, MyAppLive.IndexComponent.handle_info(:test, socket) I can see the socket data is persisting. I’m surprised this doesn’t cause a circular error though. Is this a valid operation type?
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 9- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
codeanpeace
Hmm, could you give a more concrete example of what you’re trying to achieve?
I’d suggest reading through the Managing State section of docs for
Phoenix.LiveComponentwhich covers how to message the parent LiveView viasend(self(), {:updated_card, message})or a child LiveComponent viasend_update(MyLiveComponent, data).cmo
It sounds like you’re assigning data on the child component and expecting that date to be available on the parent. Thing is, they’re two different sockets. As per @codeanpeace’s advice, use
sendto send the data from the child to the parent and assign it there.You don’t call another module’s
handle_info, you send it a message and write ahandle_infoto handle that message in the receiving module.chrisdel101
Thanks for the ideas!
I’m able to get the
sendto work on it’s own but as soon at I add the “redirect”push_patchafter it, things get out of sync.Is there an async
sendthat I can nest the redirect in to make it wait? I only found an async send_update which is the opposite of what I need.I need the
handle_paramsto run only after the socket has been updated with the new data.sendis not working super reliably for me in general. I’m needing to restart the server since it stops receiving sometimes. TBF I have this same issue with pubsub.I really didn’t want to redesign my whole solution but looks like I might have to.
polypush135
There are really two main ways.
the assigns are passed in via the mount/update callbacks
Think trickle down props (smart trunk, stupid branches)
the assigns as passed in via send_update
Using a pid you can push a new update call and pass it explicitly the assigns.
This is commonly used on components that manage their own state rather than taking the state passed in via the props which are normally trickled down from the parent component.
There maybe other ways but this is your two most common use cases.
Edit: handle_params will fire the update callback and is also typically handled at the top most component and or use send_update to push that state to a desired component. Given the update callback is on the top most parent this normally cause a cascade of update callbacks for the dependent children components.
chrisdel101
Hi @polypush135,
But I’m going this other way in this one case, from child to parent. Trying to push some data “up”, “save” it on the parent, then move on.
I think I’ll need a redesign where this isn’t the case.
polypush135
Careful to not cause a loop given you are pushing to the parent.
If you ever done react + redux you will know this level of bi directional state causes huge issues.
Again typically its top down, but you can push to any given component via the send update, just beware you may cause a loop if you push to the parent that also supplies the same component in question.
Edit: One last thought, its possible to cause the handle_params to be the trigger vs send_update and push navigation as a way of triggering the update callback. Its common to let handle_params be the first of the events to cascade.
Edit Edit:
Look at how the form module does this via the generated scaffold code, its an example of the form module pushing to the parent to let it know its been submitted. Though it does not use handle params.
cmo
Maybe don’t patch from the component? You could try doing it from the
handle_info. But I think you need to step back and think about your design.It does seem odd that you’ve got the list of users in both the parent and child and your updating the parent by sending the entire list that has changed only in the child to the parent. Are you not then assigning that to the child and thus in some kind of weird assign loop?
You might need to share a lot more of the code so people can see what’s really going on.
chrisdel101
So I’ve got it working. I think I’ve got it far enough that I won’t have to go into the weeds and post large amounts of code.
The gist is that the child component (#1) produces a list but doesn’t use the data itself. It only takes user input and processes it, which produces the list.
Then it needs to pass this list to another child component (#2), via the parent. But what if the other child (#2) needs to go back? This has been the whole problem, that state is gone and could not be saved.
I guess the solution would be to move all the computations up to the parent, and thus allow things to be passed down instead. Like, the child takes the user input (as now), but passes input to the parent instead of doing any processing here. Then parent produces the list of data and has the state in situ.
I’m surprised I haven’t run into this problem yet in 6 mos of using Phoenix. It’s b/c all other children save things to the DB, which propagates easier, and nothing goes “up.”
For now I have a kind of hack job that makes this work
It’s doesn’t seem pretty, but it works for now.
Thanks everyone for all the tips and the help!
cmo
Creating a list just to send it on and never use it does seem inefficient.
I don’t think you’ve really explained what “going back” really means in your context. But it sounds like some search thing, which you can do by updating url query params, where back and forward will work.