我有积分和一个更新积分的功能:
const [points, setPoints] = useState([])
const updatePoint = (updatedPoint) => {
setPoints(points.map(point => (point.id === updatedPoint.id ? updatedPoint : point)))
}
我已将侦听器添加到标记:
window.google.maps.event.addListener(marker, 'dragend',
function (markerLocal) {
console.log(getPoints)
}
)
如果创建后单击第一个标记,它将在控制台中显示1点。 如果我创建并单击第二个,它会向我显示2分,因此它将状态保存在侦听器内部。但是,第二次保存后,第一个标记的点总和不变(被拖动时)。这是正确的行为吗?如何获得第一个标记的2分?每当我尝试更新点列表并单击第一个标记时,它只会给我一个点-这是错误的。
答案 0 :(得分:1)
这可能是因为处理程序在声明时使用了points
,在调用之前可能会对其进行更新。我对此类问题的解决方案是将其定义为参考:
const points = useRef([]);
// This means that instead of `setPoints` you will do points.current = newValue
const updatePoint = (updatePoint) => {
points.current = points.current.map(...);
}
答案 1 :(得分:1)
尝试添加具有points
依赖项的useEffect并为Google地图设置addEventListener。此处的问题是初始addEventListener所作用的范围。在常规JS中,您将始终在范围内拥有当前值,但是在挂钩中,您的代码将引用先前渲染中的陈旧值。就您而言,您引用的是将事件附加到Google Maps时points
状态的值。我认为,这里最干净的解决方案是Leftium的解决方案,但您也可以出于“学术”目的尝试此解决方案:
const onGoogleMapsMarkerDragend = () => {
console.log(points);
}
useEffect(() => {
const dragendListener = window.google.maps.event.addListener(marker, 'dragend', onGoogleMapsMarkerDragend);
return () => {
window.google.maps.event.removeListener(dragendListener );
}
}, [points];
不确定removeListener是否有效-请查阅文档
答案 2 :(得分:0)
如果使用以前的状态来计算新状态,例如您的示例,则应将旧状态的函数而不是新值直接传递给setPoints()
:
const updatePoint = (updatedPoint) => {
setPoints((prevPoints) =>
prevPoints.map(point => (point.id === updatedPoint.id ? updatedPoint : point)
))
}
Hooks API参考中的相关部分:Identity Server docs