react icon indicating copy to clipboard operation
react copied to clipboard

[React 19] dangerouslySetInnerHTML causes repaint

Open lukahartwig opened this issue 1 year ago • 3 comments

Summary

Given the following component

function App() {
  const [count, setCount] = useState(0);

  return (
    <>
      <button onClick={() => setCount((count) => count + 1)}>{count}</button>
      <div dangerouslySetInnerHTML={{ __html: "I should only paint once" }} />
    </>
  );
}

Clicking the button should not trigger a repaint of "I should only paint once". This works as expected in [email protected] but not in [email protected] or [email protected].

  • Browser: Chrome Version 131.0.6778.86 (Official Build) (arm64)
  • OS: MacOS 15.1.1 (24B91)

[email protected]

https://github.com/user-attachments/assets/3912ae19-f0b5-4425-abd4-0c376d9f8bb7

[email protected]

https://github.com/user-attachments/assets/d486783d-819a-40fe-a9f8-8c537009e173

Source Code

lukahartwig avatar Dec 03 '24 12:12 lukahartwig

I did some bisecting

Last good version: 18.3.0-next-41b4714f1-20230328 First bad version: 18.3.0-next-85de6fde5-20230328

The issue seems to be caused by this refactoring.

lukahartwig avatar Dec 03 '24 18:12 lukahartwig

I suspect this is the same root cause as https://github.com/facebook/react/issues/31600

agriffis avatar Dec 05 '24 23:12 agriffis

Yes, this looks like the same issue.

Basically, the regression is React used to check if the passed html string has changed before applying it, but in the above mentioned refactor that was replaced by a generic equality check.

But because setDangerouslyInnerHTML takes an object, the equality check always fails and React always overrides el.innerHTML.

lukahartwig avatar Dec 06 '24 10:12 lukahartwig

This usage fix the issue for my case:

<div
  contentEditable={true}
  dangerouslySetInnerHTML={useMemo(
    () => ({ __html: value }),
    [value]
  )}
/>

SANGET avatar Jan 11 '25 09:01 SANGET

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

github-actions[bot] avatar Jun 07 '25 13:06 github-actions[bot]

bump

agriffis avatar Jun 07 '25 16:06 agriffis

Same issue here, and the fix from @SANGET works. But it's a work around IMHO.

sim51 avatar Jul 16 '25 09:07 sim51

We have the same issue!

cuonghuunguyen avatar Jul 29 '25 09:07 cuonghuunguyen

Experienced same issue, but wasn't a problem in previous versions. Fixed by using the useMemo solution.

floppydisken avatar Aug 24 '25 16:08 floppydisken

Same issue, also fixed by using the useMemo solution.

Revya7 avatar Sep 11 '25 21:09 Revya7

Same issue!

joggS1 avatar Oct 14 '25 09:10 joggS1

We also had this issue when upgrading to React 19, also fixed by the useMemo solution. A bit concerned that this level of regression was allowed into the React 19 release.

KilleRBBC avatar Oct 22 '25 09:10 KilleRBBC

+1 on having the same issue. Grateful for the useMemo suggestion - worked for us too.

juliebarwick avatar Oct 30 '25 02:10 juliebarwick