Reputation: 4112
I want to have two different tooltips when someone hovers the line and the bar. By default Tooltip
component considers both as same, but they are two different kind of data. That is why I want to have a separate tooltip for each depending on what the user hovers.
I am trying to figure this out for Line
chart first, and I am sure it will be the same for Bar
chart. I am using activeDot
object to know which dot the user is hovering over. Although it triggers the onMouseOver
function, but it contains no data to know which dot it is. Is there anything I could do to have the data as customized Tooltip
content has (CustomizedTooltip
in my code). Such as, label
, payload
and etc.
Here is what I have so far, CodeSandBox
Upvotes: 3
Views: 8811
Reputation: 446
you can add ternary operator aka conditional rendering something like this :
<Tooltip cursor={false} content={type===line?<CustomizedTooltip chartType={this.state.chartType}/>:<CustomizedTooltipBar chartType={this.state.chartType}/>} />
Upvotes: 0
Reputation: 158
The idea here is to maintain a state
of chart for which you want to show the tooltip.
Then update the state onMouseOver
and reset the state on onMouseLeave
.
Please find your update code at CodeSandBox
import * as React from "react";
import { render } from "react-dom";
import {
ResponsiveContainer,
ComposedChart,
Line,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend
} from "recharts";
const data = [
{ name: "" },
{ name: "Monday", uv: 265, pv: 800 },
{ name: "Tuesday", uv: 475, pv: 967 },
{ name: "Wednesday", uv: 624, pv: 1098 },
{ name: "Thursday", uv: 856, pv: 1200 },
{ name: "Friday", uv: 1024, pv: 1108 },
{ name: "Saturday", uv: 1116, pv: 1220 },
{ name: "Sunday", uv: 1208, pv: 1358 },
{ name: "" }
];
const formatter = (value: string) => `$${value}`;
class CustomizedTooltip extends React.PureComponent<any> {
render() {
const { label, payload, active, chartType } = this.props;
if (!active || !label || payload.length === 0) return null;
return (
<div className="i-will-customize-tooltip-later">
<p className="label">{`${label} : ${payload[chartType].value}`}</p>
</div>
);
}
}
class CustomizedDot extends React.PureComponent<any> {
render() {
const { cx, cy, value } = this.props;
if (!value) {
return null;
}
return (
<svg
x={cx - 5}
y={cy - 5}
width={10}
height={10}
viewBox="0 0 10 10"
fill="#ff7385"
>
<rect width="10" height="10" />
</svg>
);
}
}
class LineBarAreaComposedChart extends React.PureComponent<any, any> {
constructor(){
super({})
this.state = {
chartType: 0
}
}
render() {
return (
<ResponsiveContainer minHeight={500}>
<ComposedChart
width={800}
height={400}
data={data}
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
>
<CartesianGrid stroke="#efefef" vertical={false} />
<XAxis
dataKey="name"
type="category"
axisLine={false}
tickLine={false}
/>
<YAxis
dataKey="pv"
tickFormatter={formatter}
type="number"
axisLine={false}
tickLine={false}
/>
<Tooltip cursor={false} content={<CustomizedTooltip chartType={this.state.chartType}/>} />
<Legend />
<Bar name="Donation total" dataKey="pv" barSize={80} fill="#48bbee" />
<Line
name="Average dontaion trend"
type="monotone"
dataKey="uv"
data={data}
stroke="#ff7385"
dot={<CustomizedDot />}
activeDot={{
onMouseOver: (e: any) => this.setState({chartType: 1}),
onMouseLeave: (e: any) => this.setState({chartType: 0})
}}
/>
</ComposedChart>
</ResponsiveContainer>
);
}
}
render(<LineBarAreaComposedChart />, document.getElementById("root"));
Upvotes: 4