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

echarts-for-react + suspense = warning in dev and sometime blank graphic #466

Closed
astik opened this issue Dec 28, 2021 · 7 comments
Closed

Comments

@astik
Copy link

astik commented Dec 28, 2021

If graphic renders while application is suspended, we get a warning:

Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight. They should not be 0. For example, you may need to call this in the callback of window.onload. 
    at EChartsReactCore

It is coming from echarts:

  if (process.env.NODE_ENV !== 'production') {
    if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) {
      console.warn('Can\'t get DOM width or height. Please check ' + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + 'For example, you may need to call this in the callback ' + 'of window.onload.');
    }
  }

As application is suspended, dom.clientWidth and dom.clientHeight are not available. So, even though it is a echarts warning it is an issue in a React context.

This would not be a problem if it was just this warning in dev mode (even though it is quite annoying =P). Sometimes the graph is not displayed at all, leaving a whole blank block.
Resizing the window does fill in the blank block with the correct graph.

Here is a sandbox to witness the warning: https://stackblitz.com/edit/react-yquxci. I used react-query to simulate lag in order to trigger Suspense.

What would be great: having the graph render paused while in Suspend mode in order to avoid the warning and the potential blank block. Or a way to refresh the block after suspense is done suspending.

@mobeigi
Copy link
Collaborator

mobeigi commented Dec 28, 2021

Hi @astik , I think your issue belongs in: https://github.com/apache/echarts

This repo offers a wrapper around the core echarts to use with React.

@astik
Copy link
Author

astik commented Dec 28, 2021

Yes and no in fact ...

Problem is inside echarts as i said in my original message. They know the problem and an issue has been solved (apache/echarts#10478). They usually end up in reloading the graph once it cames into view (when changing tabs for example).

Still, in my case, the problem occurs when application suspends which is a React only topic. So we need a way to wrap this issue by :

  • reloading graph render when suspense is finished
  • make echarts suspense-compatible

In either way, this is a react only issue which needs to be done in this wrapper (as echart comes with this constraint).

@astik
Copy link
Author

astik commented Dec 28, 2021

After digging a little, i found some relative issues:

To sum it up, suspense wraps DOM code in a div with display:none which leads to getting 0 when looking for width or height. This is not fixable in sync mode (even with very dirty hacks). This should be ok in React 18 alpha with createRoot.

Will try tomorrow morning =)

@astik
Copy link
Author

astik commented Dec 29, 2021

Good news, it works as expected with React 18.0.0-rc0: https://stackblitz.com/edit/react-fa1hka
No more warning in the console and no more blank graphic!

Difference with previous example running React 17.0.2:

  • use React 18.0.0-rc0:
    "react": "18.0.0-rc.0",
    "react-dom": "18.0.0-rc.0",
  • change render:
// replace:
ReactDOM.render(<App />, document.getElementById("root"));
// with:
const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement);
root.render(<App />);

Of course, React 18 is not yet for production, so we'll have to wait as there is no fix scheduled for React 17 =/

This is not a bug in echarts-for-react but this is a limitation to know of ECharts+React17+Suspense.

@astik astik closed this as completed Dec 29, 2021
@gaearon
Copy link

gaearon commented Mar 29, 2022

Should be fixed in React 18.

@bolitt
Copy link

bolitt commented Jan 15, 2023

I got the same issue with React 18 in my Jest unit tests.

import { render } from "@testing-library/react";

render(<div style={{ width: "400px", height: "400px" }}><App /></div>);
// where <ReactECharts/> is included in the App.

Even though the size is set as a parent div, it still doesn't help,

Dependencies:

"react": "^18.2.0",
"react-dom": "^18.2.0",
"echarts": "^5.4.1",
"echarts-for-react": "^3.0.2",
"@testing-library/react": "^13.4.0",

In addition, if I set this in the style directly, the same warning remains: [ECharts] Can't get DOM width or height. Please check dom.clientWidth and dom.clientHeight ....

<ReactECharts option={option} style={ { width: "300px", height: "300px" } }

@bolitt
Copy link

bolitt commented Jan 15, 2023

I tried a couple of ways in Jest unit tests, and came up with an solution to overload ReactECharts.prototype.getEchartsInstance with width and height set in opts. Here is how I fix it:

// In setupTests.ts.

import * as echarts from "echarts";
import ReactECharts from "echarts-for-react";

ReactECharts.prototype.getEchartsInstance = function (): echarts.ECharts {
  const _this = this as any;
  const e = _this.echarts; // Access the protected property.
  // Explicitly add width and height in opts.
  const opts = { width: "400px", height: "400px", ..._this.props.opts };
  return (
    e.getInstanceByDom(_this.ele) || e.init(_this.ele, _this.props.theme, opts)
  );
};

Then, the warning has gone in my tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants