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.

Suspense showes warning when using ResponsiveContainer

See original GitHub issue
  • I have searched the issues of this repository and believe that this is not a duplicate.

Same issue as #1686, but can’t reopen it and it was closed without help.

Reproduction link

Edit on CodeSandbox

Steps to reproduce

Using a ResponsiveContainer inside a Suspense and lazy load an element to trigger Suspense.

What is expected?

Warning should not be logged.

What is actually happening?

Suspense will trigger following warning when the Suspense is triggered by lazy loading an element inside of it:

The width(0) and height(0) of chart should be greater than 0, please check the style of container, or the props width(100%) and height(50%), or add a minWidth(undefined) or minHeight(undefined) or use aspect(undefined) to control the height and width.
Environment Info
Recharts v2.1.8
React 17.0.2
System Windows
Browser Chrome 96.0.4664.110

Code Example:

// Test.js
import React from "react";

const Test = () => {
  return <>test</>;
};

export default Test;
// App.js
import React, { Suspense, useState, useEffect } from "react";
import { ResponsiveContainer, PieChart, Pie } from "recharts";

const Test = React.lazy(() => import("./Test"));

function App() {
  const [test, setTest] = useState(false);

  useEffect(() => {
    setTimeout(() => {
      setTest(true);
    }, 3000);
  }, []);

  return (
    <div style={{ height: 600, width: "100%" }}>
      <Suspense fallback={<div>Loading...</div>}>
        {test && <Test />}
        <ResponsiveContainer width={"100%"} height="50%">
          <PieChart>
            <Pie
              data={[
                { name: "Group A", value: 400 },
                { name: "Group B", value: 300 },
                { name: "Group C", value: 300 },
                { name: "Group D", value: 200 }
              ]}
              dataKey="value"
              cx={200}
              cy={200}
              outerRadius={60}
              fill="#8884d8"
            />
          </PieChart>
        </ResponsiveContainer>
      </Suspense>
    </div>
  );
}

export default App;

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:3
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
williamisnotdefinedcommented, Feb 9, 2022

Ok, I believe I have figured out what is happening.

When we use suspense, the “suspensed” content gets rendered in the DOM but with “display: none !important” by the react Suspense component. I strongly believe that is the reason for our warning.

There’s an issue on react github (here), its related to suspense do not be showing the children (removing the “display: none” style) after the promise / request get resolved. But what is important is this comment: here. Please, take a time to understand that solution, it is not complex.

So we should render the chart only when suspense get false as value, I mean, when the promise / request get resolved. Do I find this solution the best way? Maybe no, but it solve the warning for now.

I really would love rechart team gave some attention to this, because those warnings are really annoying when you got a lot of responsive charts in the same screen, although honestly I can’t figure out a really good solution… (Edit PS: I’m not saying that you guys don’t give the properly attention to this project, far away from this. I’m glad that all of you had helped a lot of devs and you still are doing it very well! What I mean was its just a boring issue and it’ll be great if it were solved - I didn’t mean to be rude anyway.)

Having a look at the ResponsiveContainer component here, maybe we could check if the div “.recharts-responsive-container” is visible someway of even its parent… Ok, really don’t know, but I hope to help other people by sharing that solution that verify if the suspense fallback Loader was unmounted.

I’ll let here my changes in the code:

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

interface ISuspenseContext {
  isSuspended: boolean;
}
const SuspenseContext = createContext<ISuspenseContext>({ isSuspended: true });

/*
 * 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.
 */

interface IFallbackProps {
  children?: React.ReactElement;
  setSuspended: (boolean) => void;
}

const Fallback: React.FC<IFallbackProps> = ({ setSuspended, children }) => {
  useEffect(() => {
    return () => setSuspended(false);
  }, [setSuspended]);

  return children;
};

interface ISuspense {
  children?: React.ReactElement;
  fallback?: React.ReactElement;
}

const Suspense: React.FC<ISuspense> = ({ fallback, children }) => {
  const [suspended, setSuspended] = useState(true);

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

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

export const useSuspended = (): ISuspenseContext => {
  const context = useContext(SuspenseContext);

  if (!context) {
    throw new Error(
      'useSuspended must be used within an SuspenseContext.Provider'
    );
  }

  return context;
};

export default Suspense;

Then, when inside the component which render the ResponsiveContainer I did:

...
const { isSuspended } = useSuspended();
....
return (
  <div>
      ...
      {!isSuspended && (
         <ResponsiveContainer>
               ...........
         </ResponsiveContainer>
      )}
      ...
  </div>
)

That way my warning gone 😃

But please, give me a feedback, let me know your thoughts! Probably it could be improved someway.

1reaction
wuifdesigncommented, Dec 15, 2021

i want both values to be percent, because it should match the parent size. it works perfect this way. but if i use Suspense it shows this warning whenever a component is loaded and the chart gets hidden for a moment.

the problem is, that it somehow gets a containerWidth and containerHeight of 0 when Suspense gets triggered and this will override if both values are percentages.

      let calculatedWidth: number = isPercent(width) ? containerWidth : (width as number);
      let calculatedHeight: number = isPercent(height) ? containerHeight : (height as number);

After the Suspense is finished loading it will rerender again and looks normal. but the warning in the console is just annoying.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Rechart Responsive container does not render - Stack Overflow
I have another question, do you know why the second bar doesnt render? I just see the bar with value 3. The bar...
Read more >
Suspense for Data Fetching (Experimental) - React
Approach 1: Fetch-on-Render (not using Suspense). A common way to fetch data in React apps today is to use an effect: // In...
Read more >
[Solved]-Qt "passthrough" or "container" widget-Reactjs
Can a dumb component use/render redux container component? Rechart Responsive container does not render ... Suspense after the initial page load?
Read more >
@mui/material Alert TypeScript Examples - ProgramCreek.com
This page shows TypeScript code examples of @mui/material Alert. ... The following examples show how to use @mui/material.Alert.
Read more >
Incident Response - Hybrid Analysis
Submit malware for free analysis with Falcon Sandbox and Hybrid Analysis technology. Hybrid Analysis develops and licenses analysis tools to fight malware.
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