Search code examples
javascriptreactjslabelrecharts

Recharts: How do I label only the last point on a line chart?


I'm working with the following code written by someone else:

const calculateLabel = (line, chartData, trendLabel) => {
    return ({
      x, y, stroke, value
    }) => {      
        const getLastValue = (chartData, dataKey) => {
            const values = chartData.map(item => item[dataKey]);
            let lastValue = values[values.length - 1];
            for (let i = values.length - 2; i > 0; i--) {
                if (!lastValue) {
                    lastValue = values[i];
                } else {
                    break;
                }
            }        
            return lastValue;
        };
        const lastValue = getLastValue(chartData, line.dataKey);
        const label_text = (Math.abs(value - lastValue) < 0.0000001 ? trendLabel[line.dataKey] : "");
        const dx = label_text.length > 10 ? -60 : label_text.length > 7 ? -30 : 0;
        let dy = -10;
        return (
            <text x={x} y={y} dx={dx} dy={dy} fill={stroke} className="labelText" fontSize={18} textAnchor="middle">{label_text}</text>
        );
    };
};

What this does is that it determines the location of a pre-defined label on the line. More specifically, it looks for the last data point in the line and only returns a location for that point. This is flawed in that sometimes the last data point value can appear multiple times in the data (i.e., my last data point could be 3.5 but my third data point in the line could also be 3.5, which means the label would also be returned there).

What I am trying to do is to return the location for the last x value in the line. The return statement has the following:

return ({
      x, y, stroke, value
    })

If I log x to the console, I get the x values of the line returned as individual values each time (i.e. distance from 0 on the x-axis - not the same as horizontal axis labels). What I really need is to get a list of all x values before the return statement so I can change the value of label_text to const label_text = (x===Math.max(allXValues) ? trendLabel[line.dataKey] : "");. I've tried everything I can think of and I can't figure out how to access all the x values. Am I going about this the wrong way? Mostly, I just want to ensure the label doesn't appear twice in the chart when the last data point is not unique in the chart.

Note that I can't just manually enter the last x value because the overall code creates multiple charts, rather than one, so it needs to be determined programmatically.


Solution

  • Came up with the following workaround:

    <text x={900} y={y} dx={dx} dy={dy} fill={stroke} className="labelText" fontSize={18} textAnchor="middle">{label_text}</text>
    

    This way I'm assigning an actual value to x rather than using a variable. This makes any duplicate labels overlap, so you can't see them. It's not the best solution but the best I could come up with after scouring the internet and finding no answers to similar questions.

    Ideally, I would assign the maximum width of the x-axis to x but again, Recharts doesn't make it easy to find that. If anyone knows how to get this value, please comment.