[React 19] dangerouslySetInnerHTML causes repaint
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
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.
I suspect this is the same root cause as https://github.com/facebook/react/issues/31600
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.
This usage fix the issue for my case:
<div
contentEditable={true}
dangerouslySetInnerHTML={useMemo(
() => ({ __html: value }),
[value]
)}
/>
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!
bump
Same issue here, and the fix from @SANGET works. But it's a work around IMHO.
We have the same issue!
Experienced same issue, but wasn't a problem in previous versions. Fixed by using the useMemo solution.
Same issue, also fixed by using the useMemo solution.
Same issue!
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.
+1 on having the same issue. Grateful for the useMemo suggestion - worked for us too.