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

When using React Lazy - recharts does not render properly #2566

Open
1 task done
masbaehr opened this issue Jun 4, 2021 · 11 comments
Open
1 task done

When using React Lazy - recharts does not render properly #2566

masbaehr opened this issue Jun 4, 2021 · 11 comments
Labels
bug General bug label

Comments

@masbaehr
Copy link

masbaehr commented Jun 4, 2021

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

Reproduction link

Edit on CodeSandbox

Steps to reproduce

See link, just uncomment the Lazy and comment the regular import

What is expected?

Rendering

What is actually happening?

Not rendering

Environment Info
Recharts v2.0.8
React 17.0.2
System Windows x64
Browser Chromium 91
@rosskevin
Copy link

I'm seeing the same thing, sometimes a few lines in a chart are drawn, but usually blank, and no error. Did you find a successful way to code-split this?

@rosskevin
Copy link

May be related: #2736 (comment)

@Federico-Rossi-TalentHouse

+1

@mickdewald
Copy link

I can confirm the same.
I can load the ResponsiveContainer and the Rectangle (for tooltip) lazy, but other components won't render

// Shortened

import {
    // Rectangle,
    Area,
    AreaChart,
    ReferenceLine,
    // ResponsiveContainer,
    Tooltip,
    YAxis,
    XAxis,
    ReferenceArea,
    Brush,
} from "recharts";

// Most recharts components don`t work if lazy loaded
const Rectangle = lazy(() => import("recharts").then((m) => ({ default: m.Rectangle })));
// const Area = lazy(() => import("recharts").then((m) => ({ default: m.Area })));
// const AreaChart = lazy(() => import("recharts").then((m) => ({ default: m.AreaChart })));
// const ReferenceLine = lazy(() => import("recharts").then((m) => ({ default: m.ReferenceLine })));
const ResponsiveContainer = lazy(() =>
    import("recharts").then((m) => ({ default: m.ResponsiveContainer }))
);
// const Tooltip = lazy(() => import("recharts").then((m) => ({ default: m.Tooltip })));
// const YAxis = lazy(() => import("recharts").then((m) => ({ default: m.YAxis })));
// const XAxis = lazy(() => import("recharts").then((m) => ({ default: m.XAxis })));
// const ReferenceArea = lazy(() => import("recharts").then((m) => ({ default: m.ReferenceArea })));
// const Brush = lazy(() => import("recharts").then((m) => ({ default: m.Brush })));

...

   return (
        <Suspense fallback={progressCircle}>
            <div style={{ width: "100%", height: 200 /*border: "dashed red"*/ }}>
                <ResponsiveContainer width="100%" height="100%">
                    <AreaChart data={chartSliced}  .../>
                        <YAxis .../>
                        <ReferenceLine .../>
                        <XAxis .../>
                        <Tooltip .../>
                        <Area .../>
                        <Brush .../>
                    </AreaChart>
                </ResponsiveContainer>
            </div>
        </Suspense>

@ckifer
Copy link
Member

ckifer commented Feb 23, 2023

Yep - it's probably due to how recharts generates the charts. The individual chart components are tightly coupled with their parent and every component is tightly coupled with the high level generator function. Probably without one or the other nothing can happen (just a theory)

@mickdewald
Copy link

I guess this is rather hard to change, is it? When I build for production, the largest files are

build/assets/index-8a93d023.js                                    143.00 kB │ gzip: 45.81 kB
build/assets/Edit-662a7854.js                                     237.45 kB │ gzip: 56.73 kB
build/assets/App-900491ce.js                                      249.96 kB │ gzip: 69.52 kB
build/assets/generateCategoricalChart-aaa20c99.js                 340.68 kB │ gzip: 95.38 kB
Done in 13.68s.
yarn run v1.22.19

The (internally) created generateCategoricalChart.js is pretty heavy and would certainly benefit from code splitting.

@ckifer
Copy link
Member

ckifer commented Feb 23, 2023

It certainly would, but yeah incredibly hard to change right now.

We're working on some refactoring so things are easier to understand and easier to move around. Changing this is changing how the library works though - much more than a refactor

@mickdewald
Copy link

It certainly would, but yeah incredibly hard to change right now.

We're working on some refactoring so things are easier to understand and easier to move around. Changing this is changing how the library works though - much more than a refactor

Sounds great, looking forward to it!

@masbaehr
Copy link
Author

Just letting you know what i did. Instead of cluttering my react app's dependencies and code with recharts, i use the standalone js distribution and whenever i need a chart i do this with an iframe . Not the nicest way but definetly the fastest if charts are used rarely in the app

@mhmtbsrglu
Copy link

+1 lazy not works on component when i use fallback. It works on regular import.
Module: It works when i implement lazy
Components: Not working

// Lazy load recharts components
const rechartsModule = import("recharts");

const LazyAreaChart = lazy(() => rechartsModule.then((module) => ({ default: module.AreaChart })));
const LazyArea = lazy(() => rechartsModule.then((module) => ({ default: module.Area as unknown as ComponentType<any> })));
const LazyXAxis = lazy(() => rechartsModule.then((module) => ({ default: module.XAxis as ComponentType<any> })));
const LazyYAxis = lazy(() => rechartsModule.then((module) => ({ default: module.YAxis as ComponentType<any> })));
const LazyCartesianGrid = lazy(() => rechartsModule.then((module) => ({ default: module.CartesianGrid as ComponentType<any> })));
const LazyResponsiveContainer = lazy(() => rechartsModule.then((module) => ({ default: module.ResponsiveContainer as ComponentType<any> })));
const LazyTooltip = lazy(() => rechartsModule.then((module) => ({ default: module.Tooltip as ComponentType<any> })));
const LazyReferenceLine = lazy(() => rechartsModule.then((module) => ({ default: module.ReferenceLine as ComponentType<any> })));

// ... (th

Module lazy load testing code

rechartsModule.then(module => {
  console.log(module); // Check if the module is logged successfully
});

@ckifer
Copy link
Member

ckifer commented Nov 10, 2023

No updates other than this is still currently impossible for the same reasons. Any module that relies on generateCategoricalChart cannot be lazy loaded.

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

No branches or pull requests

6 participants