![](/img/trans.png)
[英]React.js State not updating in Event Listener in useEffect Hook
[英]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.