繁体   English   中英

在事件监听器中反应挂钩保存状态错误?

[英]React hook saved state in Event Listener wrong?

我有积分和一个更新积分的功能:

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分? 每当我尝试更新点列表并单击第一个标记时,它只会给我一个点-这是错误的。

这可能是因为处理程序在声明时使用了这些points ,这些点可能会在调用之前进行更新。 我对此类问题的解决方案是将其定义为ref:

const points = useRef([]);
// This means that instead of `setPoints` you will do points.current = newValue

const updatePoint = (updatePoint) => {
   points.current = points.current.map(...);
}

尝试添加具有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是否有效-请查阅文档

如果使用先前的状态来计算新状态,如您的示例,则应将旧状态的函数而不是新值直接传递给setPoints()

const updatePoint = (updatedPoint) => {
  setPoints((prevPoints) =>
      prevPoints.map(point => (point.id === updatedPoint.id ? updatedPoint : point)
  ))
}

Hooks API参考中的相关部分: useState的功能更新

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM