Реагируйте на зависимости useEffect для подписки / отписки с помощью eslint исчерпывающего deps - PullRequest
2 голосов
/ 09 января 2020

У меня есть хук useEffect, который должен подписываться на обновления геолокации, когда компонент появляется, а затем отписываться, когда компонент исчезает. Поэтому я передаю [] в качестве зависимостей эффекта, так как хочу, чтобы он запускался только при монтировании / размонтировании.

import { useWatchPosition } from "@ionic/react-hooks/geolocation"
import React, { useEffect } from "react"

function SiteMap() {
  const { currentPosition, startWatch, clearWatch } = useWatchPosition()

  // Subscribe/Unsubscribe to geo location on component mount/unmount.
  useEffect(() => {
    startWatch()
    return clearWatch
  }, [])

  return <svg>{/* ... */}</svg>
}

, что заставляет eslint предупреждать:

React Hook useEffect имеет отсутствующие зависимости: clearWatch и startWatch. Либо включите их, либо удалите зависимость array.eslint(react-hooks/exhaustive-deps)

Поэтому я изменил это на следующее:

  useEffect(() => {
    startWatch()
    return clearWatch
  }, [startWatch, clearWatch])

, что вызывает бесконечный рендер l oop.

Я предполагаю, что бесконечность l oop вызвана библиотекой @ionic/react-hooks/geolocation, которая создает новые функции каждый раз, когда вызывается useWatchPosition(), что делает зависимости устаревшими.

Так что я должен просто отключить проверьте эту строку с помощью:

// eslint-disable-next-line react-hooks/exhaustive-deps

Или есть какой-то способ, по которому я скучаю, чтобы сделать правильную вещь здесь?

1 Ответ

6 голосов
/ 09 января 2020

Читая исходный код useWatchPosition , вы можете видеть, что функции не создаются с useCallback, это означает, что они восстанавливаются при каждом вызове ловушки.

You может хранить ссылку на функции в ref и использовать ref.current для вызова функции:

function SiteMap() {
  const { currentPosition, startWatch, clearWatch } = useWatchPosition()

  const startWatchRef = useRef(startWatch)
  const clearWatchRef = useRef()    
  clearWatch.current = clearWatch // the updated clearWatch

  // Subscribe/Unsubscribe to geo location on component mount/unmount.
  useEffect(() => {
    startWatchRef.current()

    return () => clearWatchRef.current()
  }, [])

  return <svg>{/* ... */}</svg>
}
...