htmr icon indicating copy to clipboard operation
htmr copied to clipboard

Support React 19

Open rimzzlabs opened this issue 10 months ago • 6 comments

React 19 is supported out of the box, however React internal types has been changed over time, this cause type error on latest React project

Image

should be <img /> props, but empty object instead Image

I think htmr need some adjustment on it's types to React 19

Image

rimzzlabs avatar Feb 28 '25 12:02 rimzzlabs

If anyone comes to this, here's my temporary workaround with React 19:

import Image from 'next/image'
import type { ComponentPropsWithoutRef, ComponentType, HTMLElementType } from 'react'

  const content = htmr(/*your raw html */, {
    transform: {
      img: (props) =>
        props.src ? (
          <Image
            src={props.src as string}
            width={Number(props.width)}
            height={Number(props.height)}
            alt={props.alt ?? `Media ${title}`}
            className='w-full self-center'
          />
        ) : null,
    } as {
      [tag in HTMLElementType]: ComponentType<ComponentPropsWithoutRef<tag>>
    },
  })

rimzzlabs avatar Feb 28 '25 12:02 rimzzlabs

I think htmr need some adjustment on it's types to React 19

@rimzzlabs do you manage to find a workaround for this issue as well?

ferzos avatar Mar 06 '25 13:03 ferzos

I think htmr need some adjustment on it's types to React 19

@rimzzlabs do you manage to find a workaround for this issue as well?

Yes, I posted my follow up there,

rimzzlabs avatar Mar 07 '25 20:03 rimzzlabs

UPDATE: BUILD FAILING

ld: ../../node_modules/htmr/src/types.ts:1:17
28.14  Type error: Module '"react"' has no exported member 'ReactHTML'.

rimzzlabs avatar Mar 08 '25 16:03 rimzzlabs

UPDATE: For whoever working with latest next.js (since it uses React 19), and you can't build the app with htmr, here are temporary workaround, modifying node_modules code this is very not recommended but im in a hurry 💀

on your root project directory, create a new file under /scripts/patch-htmr.js

const fs = require('fs')
const path = require('path')

// Path to the htmr types.ts file in node_modules
const htmrPath = path.join(__dirname, '../node_modules/htmr/src/types.ts')

if (fs.existsSync(htmrPath)) {
  // New content for types.ts
  const newContent = `
import React, { type HTMLElementType, type SVGElementType, type ReactNode, type ComponentType } from "react";

type ReactHTML = HTMLElementType;
type ReactSVG = SVGElementType;

export type HTMLTags = ReactHTML;
export type SVGTags = ReactSVG;
type AllTags = HTMLTags | SVGTags;

type HTMLTransform = {
  [tag in AllTags]: AllTags | ComponentType<Omit<React.ComponentProps<tag>, 'ref'>>;
};

type DefaultTransform = {
  _: <Props>(element: string | AllTags, props?: Props, children?: ReactNode) => ReactNode;
};

export type HtmrOptions = {
  transform: Partial<HTMLTransform & DefaultTransform>,
  preserveAttributes: Array<String | RegExp>,
  /** An array of tags in which their children should be set as raw html */
  dangerouslySetChildren: HTMLTags[];
};
  `

  fs.writeFileSync(htmrPath, newContent, 'utf8')
  console.log('Patched htmr successfully.')
} else {
  console.error('Could not find htmr/types.ts. Skipping patch.')
}

this will rewrite the code inside node_modules/htmr/src/types.ts

rimzzlabs avatar Mar 08 '25 19:03 rimzzlabs

Related: https://github.com/pveyes/htmr/pull/157

alebelcor avatar Apr 25 '25 04:04 alebelcor