'react-chartjs-2 custom tooltip infinity loop with setState of object
community
I am trying to create custom tooltip with react-chartjs-2, using useState to update top and left as an object, but got infinity loop. However, if use 2 x useState for top and left separately, saw it re-render 3 times for each tooltip hover action.
Can you please help me to understand why would this happen? Thanks in advance.
Here is the error message:
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at ChartComponent (http://localhost:3000/static/js/bundle.js:28289:5)
at ScatterP (http://localhost:3000/static/js/bundle.js:740:80)
Here is my code, this is the example code from react-chartjs-2 scatter plot.
import React from "react";
import {
Chart as ChartJS,
LinearScale,
PointElement,
LineElement,
Tooltip,
Legend,
} from "chart.js";
import { Scatter } from "react-chartjs-2";
ChartJS.register(LinearScale, PointElement, LineElement, Tooltip, Legend);
export const data = {
datasets: [
{
label: "A dataset",
data: Array.from({ length: 100 }, () => ({
x: Math.floor(Math.random() * (200 + 1)) - 100,
y: Math.floor(Math.random() * (200 + 1)) - 100,
})),
backgroundColor: "rgba(255, 99, 132, 1)",
pointHoverRadius: 12,
radius: 5,
},
],
};
const ScatterP = () => {
const [isTooltipShow, setIsTooltipShow] = React.useState(false);
// const [tooltipX, setTooltipX] = React.useState(0); update X and Y separately would be fine.
// const [tooltipY, setTooltipY] = React.useState(0);
const [tooltilPosition, setTooltipPosition] = React.useState({
top: 0,
left: 0,
});
const setTooltipState = (show, x, y) => {
setIsTooltipShow(show);
if (x && y) {
// setTooltipX(x);
// setTooltipY(y);
setTooltipPosition({
top: y,
left: x,
});
}
};
const showTooltip = ({ chart, tooltip }) => {
console.log(tooltip);
if (tooltip.opacity === 0) {
setIsTooltipShow(false);
return;
}
const position = chart.canvas.getBoundingClientRect();
const top = tooltip.caretY + position.y + 5;
const left = tooltip.caretX + position.x + 5;
setTooltipState(true, left, top);
// console.log(position);
// setIsTooltipShow(true);
// setTooltipX(left);
// setTooltipY(top);
};
const options = {
plugins: {
tooltip: {
enabled: false,
external: showTooltip,
},
},
scales: {
y: {
beginAtZero: true,
},
},
};
return (
<React.Fragment>
<Scatter options={options} data={data} />
{isTooltipShow && (
<div
className='absolute bg-green-200 border border-2'
// style={{ top: tooltipY, left: tooltipX }}
style={tooltilPosition}
>
<img
alt='noimage'
style={{ width: "500px", height: "600px" }}
src='https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1200px-Image_created_with_a_mobile_phone.png'
/>
tooltip content
</div>
)}
</React.Fragment>
);
};
export default ScatterP;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
