Skip to content

Bug: useInsertionEffect() cleanup function does not fire if a component is wrapped in React.lazy #26670

Closed
@JonnyBurger

Description

@JonnyBurger

React version: 18.2.0

Reproduction

import { lazy, useState, useInsertionEffect, Suspense } from "react";

export default function App() {
  const [show, setShow] = useState(false);

  return (
    <div>
      <Suspense>{show ? <LazyComp2 /> : <LazyComp1 />}</Suspense>
      <button onClick={() => setShow((s) => !s)}>Toggle</button>
    </div>
  );
}

const MyComp = () => {
  useInsertionEffect(() => {
    console.log("start1");
    return () => {
      console.log("stop1");
    };
  }, []);
};

const MyComp2 = () => {
  useInsertionEffect(() => {
    console.log("start2");
    return () => {
      console.log("stop2");
    };
  }, []);
};

const LazyComp1 = lazy(() => Promise.resolve({ default: MyComp }));
const LazyComp2 = lazy(() => Promise.resolve({ default: MyComp2 }));

Click the button twice.

Link to code example:

https://codesandbox.io/s/focused-burnell-ewgso1?file=/src/App.js:0-773

The current behavior

Logs:

start1
start2
stop2
start1

The expected behavior

start1
stop1
start2
stop2
start1

This is also the behavior of useLayoutEffect if not in strict mode.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions