Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Creating a lazy component in a hook causes infinite loop #24534

Closed
wjmao88 opened this issue May 10, 2022 · 2 comments
Closed

Bug: Creating a lazy component in a hook causes infinite loop #24534

wjmao88 opened this issue May 10, 2022 · 2 comments
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@wjmao88
Copy link

wjmao88 commented May 10, 2022

React version: 18.1.0 to 18.2.0.next (latest available on code sandbox)

Steps To Reproduce

  1. Have a component create a lazy component in a hook (useState/useMemo),
  2. Render the lazy component
  3. Infinite loop

Link to code example:
code sandbox

this works

const _lc = lazy(() => import("./SomeComp"))

export default function App() {
  const [LazyComp] = useState(_lc);
  return <LazyComp />;
}

this will infinite loop

export default function App() {
  const [LazyComp] = useState(lazy(() => import("./SomeComp")));
  return <LazyComp />;
}

and so will this (this is the actual use case I'm dealing with)

export default function App() {
  const LazyComp = useMemo(() => lazy(() => import("./SomeComp")), []);
  return <LazyComp />;
}

It seems rendering a lazy component resets the hook somehow.

@wjmao88 wjmao88 added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label May 10, 2022
@vkurchatkin
Copy link

It seems rendering a lazy component resets the hook somehow.

It does and it is completely expected. Lazy components suspend on first render, which means that all of the parent component state (including memo, etc) is thrown out.

That's why you need an external cache for Suspense when using it for data fetching and your case is basically the same.

@wjmao88
Copy link
Author

wjmao88 commented May 11, 2022

Thanks @vkurchatkin. Is there documentation/explanation somewhere? I went looking for it after seeing your comment and can't find any. On Second thought this is just what Suspense does. It unmounts the tree below and remounts it after the suspense is done, which naturally "resets" all hooks.
The simplest work around that escaped me is to wrap it in another layer of Suspense, i.e.

export default function App() {
  const LazyComp = useMemo(() => lazy(() => import("./SomeComp")), []);
  return <Suspense><LazyComp /></Suspense>;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

2 participants