Неправильно ли реагировать на сохраненное состояние ловушки в Event Listener? - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть точки и функция для обновления точек:

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 балла, поэтому он сохраняет состояние внутри слушателя.Однако после второго сохранения сумма очков за первый маркер не меняется (когда его перетаскивают).Это правильное поведение?Как я могу получить два очка за первый маркер?Всякий раз, когда я пытаюсь обновить свой список точек и нажимаю 1-й маркер, он дает мне только одну точку - это неправильно.

Ответы [ 3 ]

0 голосов
/ 24 февраля 2019

Если предыдущее состояние используется для вычисления нового состояния, как в вашем примере, вы должны передать setPoints() функцию старого состояния вместо нового значения напрямую:

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

Соответствующий разделот Hooks API Reference: Функциональные обновления для использованияState

0 голосов
/ 05 июня 2019

Попробуйте добавить useEffect с зависимостью points и установите addEventListener для карт Google.Проблема здесь - это область, над которой работает начальный addEventListener.В обычном JS у вас всегда будет текущее значение в области, однако в хуках ваш код будет ссылаться на устаревшие значения из предыдущих рендеров.В вашем случае вы ссылаетесь на значения, которые были у вас в состоянии points на момент присоединения события к Google Maps.Здесь, на мой взгляд, самое чистое решение от 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 действителен - сверьтесь с документацией

0 голосов
/ 24 февраля 2019

Вероятно, это связано с тем, что обработчик использует 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(...);
}
...