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"

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(, {name: "Phoenix"})

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


# 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)

    <Greeter {...opts} />,

  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 =;

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

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