Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 与有条件的倾听者一起反应UseEffect并取消订阅承诺!(优化Firestore onsnapshot)_Reactjs_Firebase_Google Cloud Firestore_React Hooks_Use Effect - Fatal编程技术网

Reactjs 与有条件的倾听者一起反应UseEffect并取消订阅承诺!(优化Firestore onsnapshot)

Reactjs 与有条件的倾听者一起反应UseEffect并取消订阅承诺!(优化Firestore onsnapshot),reactjs,firebase,google-cloud-firestore,react-hooks,use-effect,Reactjs,Firebase,Google Cloud Firestore,React Hooks,Use Effect,我从未找到解决我的useEffect问题的方法: 我正在使用firebase并在我的数据库上创建一个侦听器(onSnapshot),以获取对象“Player”的最后一个状态,当状态currentGroup和currentUser可用时,我可以获取该状态 const [currentGroup, setCurrentGroup] = useState(null) const [currentUser, setCurrentUser] = useState(null) const [currentP

我从未找到解决我的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())
       }) 
}
如上所述,当
currentGroup
currentUser
可用时,我调用useEffect,如果我没有设置
currentPlayer

 useEffect(() => {

   if (!currentGroup || !currentUser)  return

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

},[currentGroup,currentUser])
正如您所想,即使未重新定义
IDefineMyListener()
,也会调用
unsubscribe()
。换句话说,当
currentGroup
currentUser
更改时,此
useffect
删除了我的侦听器,而我需要它

我怎么知道

PS:如果我删除
如果(!currentPlayer)
,它当然会工作,但会不成功地获取我的数据


PS2:如果我取消订阅,我的监听器每次会被调用两次。

你可以使用
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]); 
我们将只使用
useffect
注册和注销您的侦听器

useEffect(() => {   

   //subscribe  the listener
   IDefineMyListener()

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

},[])

由于我们向useEffect传递了一个
[]
,因此在安装组件时它只运行一次。但是我们已经注册了回调。因此,每次
currentGroup
currentUser
更改时,您的回调都将运行,而无需注销侦听器。

您可以使用
useCallback
钩子解决此问题

useEffect(() => {   

   //subscribe  the listener
   IDefineMyListener()

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

},[])
首先,我们将使用
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]); 
我们将只使用
useffect
注册和注销您的侦听器

useEffect(() => {   

   //subscribe  the listener
   IDefineMyListener()

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

},[])

由于我们向useEffect传递了一个
[]
,因此在安装组件时它只运行一次。但是我们已经注册了回调。因此,每次
currentGroup
currentUser
更改时,您的回调都会运行,而不会注销您的侦听器。

问题在于我对取消订阅()的理解不正确。
useEffect(() => {   

   //subscribe  the listener
   IDefineMyListener()

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

},[])
在useEffect中我没有返回任何内容,但保存了unsubcribe函数,以便在需要时调用它

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())
        }) 
  }

  ...

问题是我对退订()的理解不好。 在useEffect中我没有返回任何内容,但保存了unsubcribe函数,以便在需要时调用它

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())
        }) 
  }

  ...

您忘记了让unsubscribe=IDefineMyListener(),对吗?顺便说一句,useCallback只调用一次,并且在第一次调用后,
currentGroup
currentUser
发生更改时从不调用。。。对不起,我编辑了我的问题,我重复了一行我有点困惑。您将在
useffect
中订阅侦听器,然后侦听器将通过
.snapshot
向您提供最新值。您的侦听器数据将被更改(因为组和用户数据已更改)
useCallback
仅被调用一次,因为
currentGroup
currentUser
可能是嵌套对象。您可能希望提供适当的键,该键可以毫无疑问地标识更改。或者您可能希望深入比较这两个对象(prev、curr),然后相应地向
useCallBack
传递一个标志。好的,对不起,我想我的问题是,我不理解unsubscribe()的概念。我写下了答案。它就像一个符咒,谢谢你的耐心:)是的,我会读这个教程,因为我不知道如何使用“useCallback”来做我需要的事情。我会让你知道的。谢谢@UtsavYou忘记了
让unsubscribe=IDefineMyListener()
,对吗?顺便说一句,useCallback只调用一次,并且在第一次调用后,
currentGroup
currentUser
发生更改时从不调用。。。对不起,我编辑了我的问题,我重复了一行我有点困惑。您将在
useffect
中订阅侦听器,然后侦听器将通过
.snapshot
向您提供最新值。您的侦听器数据将被更改(因为组和用户数据已更改)
useCallback
仅被调用一次,因为
currentGroup
currentUser
可能是嵌套对象。您可能希望提供适当的键,该键可以毫无疑问地标识更改。或者您可能希望深入比较这两个对象(prev、curr),然后相应地向
useCallBack
传递一个标志。好的,对不起,我想我的问题是,我不理解unsubscribe()的概念。我写下了答案。它就像一个符咒,谢谢你的耐心:)是的,我会读这个教程,因为我不知道如何使用“useCallback”来做我需要的事情。我会让你知道的。谢谢你@Utsav