Hacker News new | past | comments | ask | show | jobs | submit login
Phoenix LiveView: Async Assign Pattern (andyglassman.com)
146 points by gnutrino on June 14, 2023 | hide | past | favorite | 22 comments



I started using this pattern in my LiveView projects, and finally rolled it into a common module for others to use. I've found it really helps clean up the mount function, which can get pretty messy as your LiveViews grow over time.

My apologies for the terrible elixir syntax highlighting in this post. I keep putting off finding a good way to do this on Blogger.


Are you sure your import should not be:

  import Phoenix.Socket, only: [assign: 2, assign: 3]


When using LiveView I always use:

  import Phoenix.Component, only: [assign: 2, assign: 3]
https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#...

Importing from Socket should work, but you're right, the code in the post wouldn't work. They use to be in LiveView but got moved to Component.


I'm still on 17.X, so that probably explains the discrepancy here. I think I tried doing a major version bump a while back and things didn't compile so I put it on the backlog and forgot about it. It may be time to revisit before I get too far behind.


I believe you are correct. I could probably remove the imports altogether, and just prefix those functions with `Phoenix.LiveView`.


+1 for removing imports!

Not that importing is useless but single-use imports drive me a bit nuts. Even just using it a few times. It's nice to be able to jump to some code and know exactly where everything is coming from without having to jump around the file.


Knowing the origin of the function is a huge benefit, but also imports create compile time dependency. In this case, it's not an issue, but when you're importing a lot of things across your codebase, it can become an issue.


I'll take compile-time dependency over unchecked run-time dependency (almost) every time!


Ya, if you design relationships as a DAG then those sorts of compile time dependencies don't matter. Of course sometimes it can't be avoided (Phoenix router, ecto relationships) the router isn't updated very often and schemas don't have too far a reach (at least they don't if you keep them in their contexts).

I don't avoid import but I generally I strive to import one module where I'm going to be using many functions. I rarely bother with `only` unless it's absolutely necessary due to conflicts otherwise specifying `only` is a good indication I don't even need to import.


I haven't written Elixir professionally the last couple of years, but I was an early user of LiveView when it was first demoed at a conference.

As someone who currently writes applications using React Server Components, I am interested to see how concepts like LiveView evolve over time. We are now shipping significantly more HTML than before, and a lot less Javascript, as more has been moved to the server.

Makes me wish LiveView was portable to every other platform I work on, rather than having to convince companies to write more Elixir (although that isn't a bad thing).


There is a port of it to JavaScript/Typescript. https://LiveViewJS.com

It uses the same front end javascript from Phoenix and speaks the same protocol.

Note: am author


Does this work with Astro (or Next.js)?


The downside to doing this in other languages is that there is a collection of trade offs to do it well that aren’t easy outside of the BEAM.


There's https://native.live if you want to deploy it as a native app. You can also embed React Components into LiveView if you wanted. Elixir can be anywhere you want it to be.


I haven't looked into this much, but saw someone do a talk on it at ElixirConf maybe two years ago. I bet it's much more robust now.


You could look into htmx, which is a more language agnostic way to do it.


Does this work well with tests? For instance, if you click a button in a test, do you need to do something special to ensure the async update has happened before checking assertions on the HTML contents?


Yes, LiveViewTest (a module included in Phoenix LiveView) supports testing connected mounts.

You can write a test that just fetches the disconnected state, and then upgrades it to a connected state (see https://hexdocs.pm/phoenix_live_view/Phoenix.LiveViewTest.ht...).

If you want to test the result of a button click there's support for that, too, with things like `render_click`.


I mean for async assigns specifically. I did something like this in the past and had some troubles with render_click returning the html before the async update completes.


Looks really useful and neat especially the way it chains so fluently for parallerization


As I evolved the pattern over time, I found it really did help clean up a lot of code in `mount`. Once I got it working for one LiveView, it was really easy to rip out a lot of messy code in the other LiveViews. I'm definitely happy with the results! Thanks for reading.


Anyone doing similar with Swift given it also has server continuations?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: