Реагируйте UseEffect и Unsubscribe обещание с условным слушателем! (Оптимизировать Firestore onsnapshot) - PullRequest
0 голосов
/ 04 апреля 2020

Я никогда не нахожу решение для моей проблемы useEffect: я использую firebase и создаю слушатель (onSnapshot) в моей базе данных, чтобы получить последнее состояние моего объекта "Player", которое я могу получить, когда состояния currentGroup и currentUser доступны

const [currentGroup, setCurrentGroup] = useState(null)
const [currentUser, setCurrentUser] = useState(null)
const [currentPlayer, setCurrentPlayer] = useState(null)

const IDefineMyListener = () =>{

    return firebase.doc(`group/${currentGroup.id}${users/${currentUser.id}/`)
       .onSnpashot(snap =>{
            //I get my snap because it changed
            setCurrentPlayer(snap.data())
       }) 
}

Выше, я называю useEffect, когда доступны currentGroup и currentUser и (ВАЖНО), если я еще не установил currentPlayer

 useEffect(() => {

   if (!currentGroup || !currentUser)  return

   if (!currentPlayer) {
     let unsubscribe = IDefineMyListener()
     return (() => {
        unsubscribe() 
     })
   }

},[currentGroup,currentUser])

Как вы можете подумать, unsubscribe() вызывается, даже если IDefineMyListener() не переопределено. Другими словами, когда currentGroup или currentUser изменяется, этот useEffect удалял моего слушателя, тогда как мне НУЖНО ЭТО.

Как я могу понять ?!

PS: если я удаляю if (!currentPlayer), конечно, это работает, но не получит мои данные

PS2: Если я удаляю отписку, мой слушатель вызывается дважды каждый раз.

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Вы можете использовать ловушку useCallback, чтобы обойти это.

Сначала мы определим вашего слушателя с помощью useCallback и передадим массиву зависимостей аргументы как currentGroup и currentUser.

const IDefineMyListener = useCallback(event => {

   return firebase.doc(`group/${currentGroup.id}${users/${currentUser.id}/`)
   .onSnpashot(snap =>{
        //I get my snap because it changed
        setCurrentPlayer(snap.data())
   })

}, [currentGroup, currentUser]); 

И мы будем использовать useEffect только для регистрации и отмены регистрации вашего слушателя.

useEffect(() => {   

   //subscribe  the listener
   IDefineMyListener()

     return (() => {
        //unsubscribe the listener here
        unsubscribe() 
     })
   }

},[])

Поскольку мы передали [] для использованияEffect, оно будет запускаться только один раз, когда компонент установлен. Но мы уже зарегистрировали обратный звонок. Таким образом, ваш обратный вызов будет выполняться каждый раз, когда currentGroup или currentUser изменяется без отмены регистрации слушателя.

0 голосов
/ 04 апреля 2020

Проблема была в том, что я плохо понимаю отписку (). Я ничего не возвращал в своем useEffect, но сохранил функцию unsusbcribe, чтобы вызывать ее, когда мне нужно.

let unsubscribe = null //I will save the unsubscription listener inside it
const myComponent = () => {

  const [currentGroup, setCurrentGroup] = useState(null)
  const [currentUser, setCurrentUser] = useState(null)
  const [currentPlayer, setCurrentPlayer] = useState(null)

  useEffect(() => {
    if (!currentGroup || !currentUser)  {
      if(unsubscribe){
        unsubscribe() // 2 - when I dont need of my listener, I call the unsubscription function
      }
      return
    }

    if (!currentPlayer && !unsubscribe) {
      unsubscribe = IDefineMyListener()  // 1 -  I create my listener and save the unsubscription in a persistant variable
    }
  },[currentGroup,currentUser])

  const IDefineMyListener = () =>{
      return firebase.doc(`group/${currentGroup.id}${users/${currentUser.id}/`)
        .onSnpashot(snap =>{
              //I get my snap because it changed
              setCurrentPlayer(snap.data())
        }) 
  }

  ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...