Recharts: allowDuplicatedCategories breaks Tooltip - reactjs

I have a chart that redraws lines based on React state filters. By default, the tooltip appears and works for all points on the line, but once I change the state by selecting a different filter, the tooltip no longer appears. Changing allowDuplicatedCatories={true} fixes the issue, but then the tooltip doesn't appear on all points since there are duplicate categories. Is there a workaround to keep this flag as false but show the tooltip on every line without completely restructuring the data format?
Relevant code: Note: dataKeys is an array of keys that are generated when the user selects a combination of filters.
<ComposedChart data={chartData}>
<XAxis
label={{
value: "Date",
position: "bottom",
dy: 10,
fontSize: 16,
}}
tickFormatter={(tick) => {
const parts = tick.split("-");
return `${this.tickLabels[parts[1]]}/${parts[2]}`;
}}
dy={10}
dataKey="date"
tick={{ fontSize: 12 }}
padding={{ left: 20, right: 20 }}
interval="preserveStartEnd"
allowDuplicatedCategory={false}
/>
<CartesianGrid stroke="#f5f5f5" />
<Tooltip
cursor={{ stroke: "#4c5b5f", strokeWidth: 1 }}
formatter={(value) => Math.round(value)}
/>
{dataKeys.map((key, i) => (
<Line
name={`${
(this.legendLabels[key] || key).split(`|`)[0]
}, ${key.split(`|`)[1]} (Mean)`}
type="monotone"
dataKey={`amt_${key}`}
connectNulls
dot={false}
/>
))}
</ComposedChart>

Related

Is it possible to sync between Line Chart and Scattered Chart in Recharts?

I have a scattered and a line chart type. I am trying to sync between these charts type.
I have these problems:
the tooltip does not appear in scattered chart when I hover to line chart, but the "cursor line" sync
when I hover in the scattered chart, there is no sync between line and scattered chart
the details can be seen here:
here is the code I have
const Chart = ({ type, matrixData, index, diagcodeLabel }) => {
const getMinValue = Math.min(...matrixData.map((data) => data[type]));
const getMaxValue = Math.max(...matrixData.map((data) => data[type]));
return (
<div className="chart">
<div className="title">{type}</div>
<ResponsiveContainer key={"responsiveInformation"} width="100%" height={170}>
{type === "DIAGCODE" ? (
<ScatterChart
syncId="chart"
width={1200}
height={400}
margin={{
top: 20,
right: 20,
bottom: 20,
left: 20,
}}
>
<YAxis
type="number"
dataKey="dLevel"
tickFormatter={(value) => {
return Object.keys(diagcodeLabel).find((k) => diagcodeLabel[k] === value);
}}
/>
<Tooltip />
<CartesianGrid strokeDasharray="3 3" className="chartGrid" />
<Legend layout="vertical" content={<CustomLegend />} />
<Scatter name="DiagCode" data={matrixData} fill="#8884d8" shape={"circle"}>
{matrixData.map((entry, index) => {
return (
<Cell
key={"cell-${index}"}
fill={entry.IsLockout === "Lockout" ? "#5fb0ff" : "rgb(172, 45, 45)"}
/>
);
})}
</Scatter>
</ScatterChart>
) : (
<LineChart
syncId="chart"
width={500}
height={50}
data={matrixData}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" className="chartGrid" />
<YAxis dataKey={type} domain={[getMinValue, getMaxValue]} />
<Tooltip />
<Line type="monotone" dataKey={type} stroke="#8884d8" activeDot={{ r: 8 }} />
</LineChart>
)}
</ResponsiveContainer>
</div>
);};
Is there a way I could sync them ?
I think this kind of feature is underdevelopment https://github.com/recharts/recharts/issues/1541
So, I ended up using composed charts (Scattered and Bar) https://recharts.org/en-US/examples/LineBarAreaComposedChart and I set the fillOpacity transparent for Bar. but I am not sure if it is the best workaround...

recharts line chart 'Y' axis range issue

I have a line chart that displays several lines of data, everything works as expected, the only issue is that when the chart is displayed there is huge blank space inside the chart itself, I have been checking the data range I am sending but seems fine, all values appear, have been also checking for some styling issue but I dont seem to see anything strange, sadly the docs are very limited for the styling regard that I am not able yet to find a solution.
<ResponsiveContainer aspect={10.0 / 3.0}>
<LineChart margin={{left: 30, top: 30}} width={730} height={300}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis
dataKey="month"
type="category"
allowDuplicatedCategory={false}
allowDecimals={false}
/>
<YAxis
padding={{top: 28}}
interval={0}
ticks={range}
tickSize={2}
tickFormatter={val => getLocaleString(val)}
label={{
value: 'EUR',
position: {x: 40, y: 0},
className: 'chart__label',
}}
/>
<Tooltip />
<Legend
onMouseOver={mouseOverLegend}
onMouseLeave={mouseLeaveLegend}
/>
{data.map((data, index) => {
const namePostfix = `EUR ${yearsDataChart[index]}`
const stroke =
hoverIndex === index || !legendHover
? colorsChart[index]
: COLOR_HOVER
const costName = `${translate('cost')} ${namePostfix}`
const revenueName = `${translate('revenue')} ${namePostfix}`
return [
<>
<Line
dataKey="revenue"
data={data}
name={revenueName}
stroke={stroke}
/>
<Line
dataKey="cost"
data={data}
name={costName}
stroke={
hoverIndex === index || !legendHover
? colorsChartProvider[index]
: stroke
}
/>
</>,
]
})}
</LineChart>
</ResponsiveContainer>
the result is :
hope someone has an idea of what could be the issue here

How to add a custom svg as the line/tooltip for recharts

I have a line chart with two lines.
For one of the lines, I want to use a custom svg to represent it in the chart. See screenshot.
How can I do this?
Here's my code:
<LineChart
// width={800}
onClick={() => {}}
height={300}
data={this.state.data}
// margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
>
<XAxis dataKey="to_char" />
<YAxis
tickFormatter={value => {
let val = value / 1000000;
return `$${new Intl.NumberFormat("en").format(val)}m`;
}}
/>
<CartesianGrid strokeDasharray="3" vertical={false} />
<Tooltip />
<Legend />
<Line
dot={false}
type="monotone"
dataKey="predictedprice"
stroke="#1C85E8"
activeDot={{ r: 8 }}
name="True Home Estimateā„¢"
strokeWidth={3}
/>
<Line
type="monotone"
name="Sold Price"
dataKey="soldprice"
stroke="#82ca9d"
shape="star"
/>
</LineChart>
You should be able to add the shape property to ReferenceDot or ReferenceArea - I'm not sure if the shape properly can be used on regular properties, but here's a link I found to a GitHub conversation that talks more about this:
https://github.com/recharts/recharts/issues/922

How to prevent breaking axis long labels in React Recharts?

I'am using React Recharts (http://recharts.org/en-US/) to show some chart data and I need to show formatted values nearby axis. Axis values is separated by spaces, for example 1 000 000 $. React Recharts is breaking values into separate lines
How to prevent breaking labels and show it fully at the same line?
Have you tried using a tick formatter? I tried to reproduce your problem but it couldn't.
Here is a re-purposed chart that is working just fine for me.
<ResponsiveContainer height={400} width="100%">
<ComposedChart
height={400}
width="100%"
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
>
<CartesianGrid />
<XAxis dataKey="name" />
<YAxis
unit="$"
dataKey="y"
tickFormatter={val => val.toLocaleString().replace(/,/g, " ")}
/>
<Scatter
name="A school"
data={[
{ name: "Jill", y: 3000000 },
{ name: "Eve", y: 5000000 },
{ name: "Audrey", y: 1000000 },
{ name: "Jaqueline", y: 7000000 }
]}
fill="#8884d8"
/>
<Tooltip />
</ComposedChart>
</ResponsiveContainer>
Let me know if misunderstood your question.
You can specify the width for tick
For example,
<YAxis tick={{ width: 75 }} tickFormatter={formatter} domain={yDomain} allowDataOverflow/>

How to change font family for React Recharts library X-axis / Y-axis ticks?

My task is fairly simple: all I want to do is change the font-family to Roboto, sans-serif for the x-axis and y-axis "ticks" (ie. the values along both axes).
I can change the font size of the x-axis tick with:
<XAxis tick={{ fontSize: 'sans-serif!important' }} />
But this doesn't work:
<XAxis tick={{ fontFamily: 'sans-serif' }} />
The only other option I can see is to use the tickFormatter property specified in the documentation which only takes a function, see here: http://recharts.org/#/en-US/api/XAxis
In this project we are using the functional-style of programming in React using the Recompose utility library so we are rendering JSX in the "pure" function style and not with normal React classes.
This is the best guess I could come up with is:
const xAxisTickFormatter = name => {
return <div style={{ fontFamily: 'sans-serif' }}>{name}</div>;
};
export const LineChart = ({ data, isMobile }) => {
console.log(data);
return (
<C
width={isMobile ? 400 : 650}
height={400}
data={data}
margin={{ top: 5, right: 20, left: 10, bottom: 5 }}
>
<XAxis
tickFormatter={xAxisTickFormatter}
dataKey="date"
name="Date"
style={{ fontFamily: 'sans-serif' }}
/>
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip wrapperStyle={{ fontFamily: 'Roboto, sans-serif' }} />
<Legend
wrapperStyle={{ fontFamily: 'Roboto, sans-serif' }}
verticalAlign="bottom"
height={36}
/>
<Line
type="linear"
dataKey="price"
name="Price"
stroke="#8884d8"
activeDot={{ r: 8 }}
/>
<Line
type="linear"
dataKey="marketAverage"
name="Market Average"
stroke="#82ca9d"
/>
</C>
);
};
This outputs [object, Object] along the x-axis, see screenshot:
The only similar official example from the docs uses the old createClass syntax here: https://jsfiddle.net/alidingling/9y9zrpjp/
Any help would be greatly appreciated as I have googled as many similar problems as possible and spent about half a day on this problem so far.
The style attribute works fine for me; in recharts 2.0.0-beta.1 at least.
<XAxis
dataKey="date"
style={{
fontSize: '1rem',
fontFamily: 'Times New Roman',
}}
/>
<YAxis
style={{
fontSize: '0.8rem',
fontFamily: 'Arial',
}}
/>
Your tickFormatter function should return just a string, not a React Element.
Why don't just set the font family and whatever else you want to overwrite via CSS?
We have something similar:
.recharts-cartesian-axis-tick {
font-size: 1.4rem;
font-family: Roboto, sans-serif;
}
CSS is the best way to go. However, there is at least one scenario where you will want to insert the font-family directly. When trying to convert your Recharts Component from SVG to PNG/JPEG, your CSS will not render the font you set.
NOTE: Your Recharts is rendered as an SVG on the screen.
In my CSS, I had 'Roboto' as my font (first image) and when I converted to PNG, my font rendered as 'Times New Roman' (second image)
To solve this, do this:
<XAxis
fontFamily={'Roboto, sans-serif'}
/>
<YAxis
fontFamily={'Roboto, sans-serif'}
/>
Just add className property in parent class like in your case
<C className="fontName">
and in css
.fontName {
font: normal normal 900 9px/12px Avenir; // font name
letter-spacing: -0.29px;
}
I had a hard time trying to change the color of ticks of axes. Actually, I had a conflict between "tick:{color...}" and "stroke" which both impact it.

Resources