簡體   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