Reactjs 与有条件的倾听者一起反应UseEffect并取消订阅承诺!(优化Firestore onsnapshot)
我从未找到解决我的useEffect问题的方法: 我正在使用firebase并在我的数据库上创建一个侦听器(onSnapshot),以获取对象“Player”的最后一个状态,当状态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
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