tme_317
I’ve been experimenting using the recently landed LV-JS interop features to render React components inside LiveView. I can simplify my app by doing much with LV but don’t want to rewrite all my existing components yet!
It works pretty well but ran into 2 minor issues. I am rendering the React components modeled on the way GitHub - geolessel/react-phoenix: Make rendering React.js components in Phoenix easy · GitHub does it which is pretty simple. You render a div in the LV with data- properties (props map encoded as JSON) like such:
~L"""
<div data-react-class="Components.LikeButton" data-react-props="<%= Jason.encode!(@props)%>" phx-hook="React" phx-update="ignore"></div>
"""
Then in the new LiveView Hooks mounted and updated callbacks in my entrypoint JS I have this:
// ...
import LikeButton from "../zlib/LikeButton.js";
window.Components = {
LikeButton
};
function renderReact(el, pushEvent) {
const targetId = document.getElementById(el.dataset.reactTargetId);
const targetDiv = targetId ? targetId : el;
const reactProps = el.dataset.reactProps ? el.dataset.reactProps : "{}";
const reactElement = React.createElement(
eval(el.dataset.reactClass),
Object.assign(JSON.parse(reactProps), { pushEvent: pushEvent })
);
ReactDOM.render(reactElement, targetDiv);
}
let Hooks = {};
Hooks.React = {
mounted() {
this.pushEvent("hello_from_react", "1234"); // THIS WORKS!
renderReact(this.el, this.pushEvent);
},
updated() {
renderReact(this.el, this.pushEvent);
}
};
let liveSocket = new LiveSocket("/live", { hooks: Hooks });
liveSocket.connect();
Biggest issue is the use of the pushEvent callback… it works if I use it directly in the mounted function but I want to be able to pass the function as a prop to my React tree so the children components can easily push events to the server. However, when calling it in the React component I am getting Uncaught TypeError: Cannot read property 'pushWithReply' of undefined. I’m sure my lack of JS knowledge has me doing it wrong since I think it’s a method and maybe needs this context hanging around or something?
Second issue is I have to call duplicate renderReact in both the mounted and updated callbacks for everything to work… but the component is re-created and re-rendered every time any LV assigns update (not just props changes affecting this specific element). If I just call in mounted it won’t re-render when the server changes the props so I have to call it in both places. I was thinking updated would only be called on a specific hook when assigns change affecting that specific element? This part is working so far but seems like it will be slow when having to re-render many components.
Has anyone else successfully integrated React components into LV yet using the new hooks interop? I think this hybrid approach will work great and allow the best of both worlds once these issues are figured out.
Thanks!
Trending in Questions
Other Trending Topics
Latest Phoenix Threads
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #ai
- #iex
- #graphql
- #elixirconf-us
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 1- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
tme_317
In case anyone comes across this post… there is a new library that solves this which I just evaluated and it works great!
https://github.com/fidr/phoenix_live_react