How to mount a React component with a LiveView hook?

I’ve tried mounting a React component with a LiveView hook (btw, calling these hooks makes it very hard to Google for anything since React has hooks too :frowning_face: ) like so:

<div id="id-of-div"
     phx-hook="NameOfHook"
     phx-update="ignore"></div>

but I’m getting nowhere. I’ve tried following this link with no success. What I have:

# assets/js/app.jsx

...

import mounter from "./mounter";

let Hooks = {}

Hooks.Greeter = {
	mounted() {
		this.unmountComponent = mounter.mount(this.el.id, {name: "Phoenix"})
	},

	destroyed() {
  	if (!this.unmountComponent) {
      console.error('Greeter unmountComponent not set')
      return
    }

    this.unmountComponent(this.el)
  },
}

# assets/js/mounter.tsx

import { render, unmountComponentAtNode } from 'react-dom'

import { Greeter, GreeterOpts } from './greeter'

export default function mount(id: string, opts: GreeterOpts) {
  const rootElement = document.getElementById(id)

  render(
    <Greeter {...opts} />,
    rootElement
  )

  return (el: Element) => {
    if (!unmountComponentAtNode(el)) {
      console.warn('unmount failed', el)
    }
  }
}
# assets/js/greeter.tsx

import React from "react";

export interface GreeterProps {
    name: string;
}

export const Greeter: React.FC<GreeterProps> = (props: GreeterProps) => {
    const name = props.name;

    return (
        <section className="phx-hero">
          <h1>Welcome to {name} with TypeScript and React!</h1>
          <p>Peace-of-mind from prototype to production</p>
        </section>
    );
};

I know about phoenix-live-react, but I’d rather learn how to do this without it. I have no esbuild errors, but the React component doesn’t show up on the div in index.html.heex. Any pointers welcome!

Figured it out, wrote a blog post about it React and Phoenix LiveView in 2022 :: Bruno Antunes — Thoughts, rants, ideas

3 Likes