使用条件侦听器响应 UseEffect 和取消订阅承诺!(优化 Firestore 快照)

Dam*_*ito 0 firebase reactjs google-cloud-firestore react-hooks use-effect

我从来没有找到解决我的 useEffect 问题的方法:我正在使用 firebase 并在我的数据库上创建一个监听器(onSnapshot)来获取我的对象“Player”的最后状态,当状态currentGroupcurrentUser可用时我可以获得

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())
       }) 
}
Run Code Online (Sandbox Code Playgroud)

currentGroup正如上面,当和可用时,我调用 useEffect currentUser,并且(重要)如果我还没有设置currentPlayer

 useEffect(() => {

   if (!currentGroup || !currentUser)  return

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

},[currentGroup,currentUser])
Run Code Online (Sandbox Code Playgroud)

正如您所想, unsubscribe()即使IDefineMyListener()没有重新定义,也会被调用。换句话说,当currentGroupcurrentUser改变时,这useEffect会删除我的听众,而我需要它。

我怎样才能弄清楚?

PS:如果我删除if (!currentPlayer),它当然可以工作,但除非得到我的数据

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

Uts*_*tel 5

您可以使用useCallback钩子来解决这个问题。

首先,我们将使用定义您的侦听器useCallback,并将参数指定为依赖项数组currentGroupcurrentUser

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]); 
Run Code Online (Sandbox Code Playgroud)

我们只会用来useEffect注册和注销您的监听器。

useEffect(() => {   

   //subscribe  the listener
   IDefineMyListener()

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

},[])
Run Code Online (Sandbox Code Playgroud)

由于我们传递了一个[]useEffect ,它只会在组件安装时运行一次。但我们已经注册了回调。因此,您的回调将在每次currentGroupcurrentUser发生变化时运行,而无需取消注册您的侦听器。