Does Phoenix have something similar to the React Context API that can be used with LiveView components?

I’m loving LiveView Components but I’m finding myself passing props down multiple levels. Does Phoenix have anything resembling the React Context API that can make data available to all child components without the need for this “prop drilling”?

In a perfect world, I’d be able to add something to the assigns of a parent component (likely namespaced to avoid conflicts) then access it in the mount, update or render functions of a child.

I’ve seen something similar in the Surface library, but I’d like something more “vanilla” that doesn’t require me to move to a whole new set of components.

I dont think that there is (havent checked out the latest relase that much) but you could setup an Agent or Genserver that holds data and can be accessed from different components.

However that is not the path I would take. I would avoid to much nested components :slightly_smiling_face:.

You can jerry rig this by using the process dictionary since all components live in the parent liveview process but it would be a bit difficult to get it to work in a properly reactive way.

Surface Contexts essentially solve this by passing the context items all the way down the tree with generated code from the compile phase.

Thank god LiveView has nothing to do with hooks!!

I think you would handle such use case with a stateful component (Surface) that subscribes to updates using message passing - that call update(socket…)

You cant subscribe to anything from a component, pubsub goes between processes and a component lives in the parent liveview.

You’re right back at needing to pass the data down to the component.

Seeing as LiveView Components run in the same process as the parent LiveView I feel like it should be possible to expose data from the view, directly to the child components, without the need to pass everything via props.

In my use case, I have a list (a flat map that represents a tree) of stateless components that I render recursively. The code would be simpler if I didn’t have to pass it, and the currently selected state, all the way down the tree when rendering.

A few people have suggested using an Agent for this, holding the current state of each user in a separate process and using messages to update the LiveView components… This just feels a little heavy, but it could just be a lack of familiarity on my part.

Edit: Reading through the docs, if only assign_new/3 worked in LiveView components, I think that would solve my problem…

You can store in the process dictiomary.

Getting data in and out is not hard, its having the render kick off (or not kick off all the time) is the problem as this is completely outside change tracking.

Which is why Surface solved it by generating code to do all the boring assign passing.

2 Likes

Thanks Oliver, I might just wait for the new version of Surface then (for Phoenix 1.6) and use their Context wrapper.