I want to display a list of coordinates that I got from click event on DIV. I want the listener works only when a button was clicked.
import { createRoot } from "react-dom/client";
import React, {useCallback, useEffect, useState} from 'react'
const AppRestoration = () => {
const [active, setActive] = useState(false);
const [coordinates, setCoordinates] = useState([]);
const handleClick = useCallback((event) => {
console.log(coordinates) // is empty array
setCoordinates((prevCoordinates) => [...prevCoordinates, event.clientX]
);
}, [setCoordinates]);
useEffect(() => {
console.log("Coordinates:", ...coordinates); // When they update
}, [coordinates]);
return (
<div>
<div
style={{ width: "200px", height: "200px", backgroundColor: "red" }}
onClick={handleClick}
>
ici
</div>
<button onClick={() => setActive((prev) => !prev)}>
{active ? "clicked" : "not"}
</button>
<SecondComponent secondCParam={coordinates} />
</div>
);
};
const SecondComponent = ({ secondCParam }) => {
return (
<ul>
{secondCParam.map((coord) => (
<li key={crypto.randomUUID()}>{coord}</li>
))}
</ul>
);
};
createRoot(document.getElementById("root")).render(<AppRestoration />)
The problem is : in handleClick(event) I can not filter "coordinates", it is always an empty array. To refresh it, I have to click on the button, so handleClick one more time. How to avoid it?
Why not add the click handler to the element, and do it the React way?
<div
style={{ width: "200px", height: "200px", backgroundColor: "red" }}
onClick={handleClick}
>
const handleClick = useCallback(({ clientX }) => {
setCoordinates((prevCoordinates) =>
!prevCoordinates.includes(clientX)
? [...prevCoordinates, clientX]
: prevCoordinates
);
}, [setCoordinates]);
Also, a state called state
is ambiguous. You should rename it to a more appropriate name. For the time being, I named it active
, since the button toggles.
const { useCallback, useEffect, useState } = React;
const AppRestoration = () => {
const [active, setActive] = useState(false);
const [coordinates, setCoordinates] = useState([]);
const handleClick = useCallback((event) => {
setCoordinates((prevCoordinates) =>
!prevCoordinates.includes(event.clientX)
? [...prevCoordinates, event.clientX]
: prevCoordinates
);
}, [setCoordinates]);
useEffect(() => {
console.log("Coordinates:", ...coordinates); // When they update
}, [coordinates]);
return (
<div>
<div
style={{ width: "200px", height: "200px", backgroundColor: "red" }}
onClick={handleClick}
>
ici
</div>
<button onClick={() => setActive((prev) => !prev)}>
{active ? "clicked" : "not"}
</button>
<SecondComponent secondCParam={coordinates} />
</div>
);
};
const SecondComponent = ({ secondCParam }) => {
return (
<ul>
{secondCParam.map((coord) => (
<li key={crypto.randomUUID()}>{coord}</li>
))}
</ul>
);
};
ReactDOM.createRoot(document.getElementById("root")).render(<AppRestoration />);
.as-console-wrapper { max-height: 4rem !important; }
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>