i am still a beginner in React and i've come upon a problem which i don't know how to resolve, i have a parent component which renders a polygon on svg, based on points array
const Zone = ({ zone }) => {
const [points, setPoints] = useState(zone.points);
const updatePoint = (startPoint, endPoint) => {
if (!comparePoints(startPoint, endPoint)) {
setPoints(
points.map((point) =>
comparePoints(point, startPoint) ? endPoint : point
)
);
}
};
const comparePoints = (point1, point2) => {
if (point1.x === point2.x && point1.y === point2.y) {
return true;
} else {
return false;
}
};
const renderZone = () => {
if (points) {
return (
<g className='polygon' transform={"translate(0,0)"}>
<polygon points={getPointsString(points)} />
{points.map((point) => (
<Point
key={getReactKey("point")}
x={point.x}
y={point.y}
r={4}
updatePoint={updatePoint}
/>
))}
</g>
);
}
return null;
};
return <>{renderZone()}</>;
};
and a Point component which represents a single point on svg canvas
const Point = ({ x, y, r, snapRange, resolution, isEditing, updatePoint }) => {
const [position, setPosition] = useState({
x: x,
y: y
});
const pointRef = useRef(null);
//Altering point coordinates based on drag
const dragPoint = (event) => {
if (!isEditing) return;
let gridX = 0;
let gridY = 0;
const _x = event.x;
const _y = event.y;
const modX = _x % resolution;
const modY = _y % resolution;
const closeToHorizontal =
modY <= snapRange || modY >= resolution - snapRange;
const closeToVertical = modX <= snapRange || modX >= resolution - snapRange;
if (closeToHorizontal & closeToVertical) {
gridY = Math.round(_y / resolution) * resolution;
gridX = Math.round(_x / resolution) * resolution;
} else if (closeToHorizontal) {
gridY = Math.round(_y / resolution) * resolution;
} else if (closeToVertical) {
gridX = Math.round(_x / resolution) * resolution;
}
setPosition({
x: gridX === 0 ? _x : gridX,
y: gridY === 0 ? _y : gridY
});
};
// add drag handlers on mount
useEffect(() => {
const point = pointRef.current;
// add event listeners on component mount if in editing mode
if (isEditing) {
const dragBehavior = d3.drag().on("drag", dragPoint);
d3.select(point).call(dragBehavior);
}
// remove listener on component unmount or leaving editing mode
return () => {
d3.select(point).on("mousemove.drag", null);
};
});
useEffect(() => {
updatePoint({ x, y }, position);
});
return (
<circle
ref={pointRef}
cx={position.x}
cy={position.y}
r={r}
className={isEditing ? "poly-point" : "hidden"}
/>
);
};
draggin is working fine but i want to update the new position of a point in points array of a Zone component to do so i call
useEffect(() => {
updatePoint({ x, y }, position);
});
so on each position state change it updates points array in Zone component, after trying dragging a circle i get the error:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
which points on this method in Point component:
setPosition({
x: gridX === 0 ? _x : gridX,
y: gridY === 0 ? _y : gridY
});
my guess is that after rerendering it tries to use setPosition method which points on unmounted component, any clues how to make it right?