Search code examples
reactjsrecharts

Rechart Legend masking the chart in Mobile


Is there a way to prevent the Legend in Recharts from hiding the chart in Mobile? Please see the image below

Legend overlaps with the chart itself in mobile and smaller screens

<ResponsiveContainer width='100%' aspect={5.0 / 3.0}>
    <LineChart data={dataPoints} margin={{ top: 5, right: 10, left: 10, bottom: 5 }}>
        <XAxis dataKey="Index" domain={['auto', 'auto']} label={xlabel} />
        <YAxis
            domain={['auto', 'auto']}
            tickFormatter={formatTick}
            label={{ value: ylabel, angle: -90, position: 'left' }}
        />
        <Tooltip />
        <Legend iconType="plainline" />
        <CartesianGrid stroke="#eee" strokeDasharray="5 5" />
        {Object.keys(linesSettings).map((line, index) => {
            return <Line
                key={index}
                dataKey={line}
                stroke={linesSettings[line].color}
                dot={false}
                strokeWidth={linesSettings[line].width}
            />
        })}
    </LineChart>
</ResponsiveContainer>


Solution

  • You can conditionally display/hide legend based on the screen size. Basically, attach a resize event inside useEffect and maintain & update a boolean state showLegend upon resize.

    Working demo here

    Code Snippet

    import React, { useState, useEffect } from "react";
    import "./styles.css";
    import {
      LineChart,
      Line,
      XAxis,
      YAxis,
      CartesianGrid,
      Tooltip,
      Legend
    } from "recharts";
    const data = [
      { name: "Page A", uv: 4000, pv: 2400, amt: 2400 },
      { name: "Page B", uv: 3000, pv: 1398, amt: 2210 },
      { name: "Page C", uv: 2000, pv: 9800, amt: 2290 },
      { name: "Page D", uv: 2780, pv: 3908, amt: 2000 },
      { name: "Page E", uv: 1890, pv: 4800, amt: 2181 },
      { name: "Page F", uv: 2390, pv: 3800, amt: 2500 },
      { name: "Page G", uv: 3490, pv: 4300, amt: 2100 }
    ];
    export default function App() {
      const [showLegend, setShowLegend] = useState(true);
    
      useEffect(() => {
        function handleResize() {
          if (window.innerWidth < 800 && showLegend) {
            setShowLegend(false);
          } else if (window.innerWidth >= 800 && showLegend === false) {
            setShowLegend(true);
          }
        }
        window.addEventListener("resize", handleResize);
        return () => window.removeEventListener("resize", handleResize);
      }, [showLegend]);
      console.log(showLegend);
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <LineChart
            width={600}
            height={300}
            data={data}
            margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
          >
            <XAxis dataKey="name" />
            <YAxis />
            <CartesianGrid strokeDasharray="3 3" />
            <Tooltip />
            {showLegend && <Legend />}
            <Line
              type="monotone"
              dataKey="pv"
              stroke="#8884d8"
              activeDot={{ r: 8 }}
            />
            <Line type="monotone" dataKey="uv" stroke="#82ca9d" />
          </LineChart>
        </div>
      );
    }