question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

React.Suspense provide a lifecycle so components can handle the `display:none` removal

See original GitHub issue

Do you want to request a feature or report a bug?

It’s a feature.

What is the current behavior?

React.Suspense mounts its children with a display: none style if a promise is thrown. Once the thrown promise is resolved, React removes the display: none style.

What is the expected behavior?

The children components have no easy way to know when the display: none style is removed by React. This is problematic when one child component needs to read from the DOM layout to correctly display its elements. Most people wait for the componentDidMount callback to trigger, but because the element is display: none, it can’t read any value from the DOM layout.

The issue was discovered in https://github.com/mui-org/material-ui/issues/14077. I believe that React should provide a lifecycle so the children components know when they are visible, that it’s safe to do layout computations.

The best workaround I’m aware of it to use the Intersection Observer API but it requires a polyfill on IE 11 and Safari.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

Version: 16.7.0-alpha.2

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:32
  • Comments:34 (13 by maintainers)

github_iconTop GitHub Comments

3reactions
gaearoncommented, Jun 16, 2021

Small update.

We released 18 alpha for libraries authors to start testing. Notably, there is no concurrent “mode” anymore, instead you opt into features as you use them. So it’s much easier to adopt.

The new behavior is to delay effects from firing until the tree unsuspends, which solves a bunch of issues like in this thread. See https://github.com/mui-org/material-ui/issues/14077#issuecomment-861965259 for a concrete example.

3reactions
codymlcommented, Mar 22, 2020

Had this same issue trying to trigger a transition on suspended component mount; ended up writing a wrapped Suspense that passes suspended status to descendants via context. Also relies on potentially hacky approach of tracking mount status of the fallback, but might help:

import React, {
  useEffect,
  useState,
  Suspense as ReactSuspense,
  createContext,
  useContext,
} from 'react';
import { node } from 'prop-types';

const SuspenseContext = createContext();

/*
 * Suspense apparently renders a suspended tree before it resumes,
 * hiding it with `display: none;`.  This tweaked version lets child
 * components use the `useSuspended` hook to know if they're in a
 * rendered-while-suspended tree.
 */

export default function Suspense({ fallback, children }) {
  const [suspended, setSuspended] = useState(true);
  const Fallback = props => {
    useEffect(() => {
      setSuspended(true);
      return () => setSuspended(false);
    }, []);

    return props.children;
  };

  return (
    <ReactSuspense fallback={<Fallback>{fallback}</Fallback>}>
      <SuspenseContext.Provider value={suspended}>
        {children}
      </SuspenseContext.Provider>
    </ReactSuspense>
  );
}

Suspense.propTypes = {
  fallback: node,
  children: node,
};

Suspense.defaultProps = {
  fallback: null,
  children: null,
};

export function useSuspended() {
  return useContext(SuspenseContext);
}

Then, you can do something like this: https://codesandbox.io/s/wild-feather-vynpq. Might need to be modified for situations with multiple nested Suspense/lazy?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Suspense for Data Fetching (Experimental) - React
Suspense lets your components “wait” for something before they can render. ... Suspense support, using it from React components feels very natural.
Read more >
Prevent react suspense hide the content - Stack Overflow
I want to keep the content visible and I will make a custom fallback component like the youtube. <Suspense fallback={<div>Loading...</div>} ...
Read more >
How Suspense Works in React 18 - Better Programming
The React Suspense feature was released as part of React 16 version. ... Some components can be removed and re-added later to the...
Read more >
How to Use React Suspense to Improve Your UI Load Time
Suspense is a useful tool provided by the React library that allows developers more control over UI loading states.
Read more >
Removing State and Effects with Suspense! - YouTube
... to make arbitrary asynchronous code work with Suspense so you can ... components, using an observer from Firebase and the react -suspend ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found