Javascript Firestore onSnapshot如何侦听React Native中的更改?

Javascript Firestore onSnapshot如何侦听React Native中的更改?,javascript,firebase,react-native,google-cloud-firestore,Javascript,Firebase,React Native,Google Cloud Firestore,我在多个地方看到人们将侦听器代码放在componentDidMount中,但是,我想知道它是如何工作的,因为componentDidMount只调用一次,因此它应该只获取一次。当Firestore中发生更改时,它如何再次获取 示例代码: componentDidMount() { if(this.state.screen === 7){ var query = firestore().collection('Collection').doc().collection('sub

我在多个地方看到人们将侦听器代码放在
componentDidMount
中,但是,我想知道它是如何工作的,因为
componentDidMount
只调用一次,因此它应该只获取一次。当Firestore中发生更改时,它如何再次获取

示例代码:

componentDidMount() {
  if(this.state.screen === 7){
        var query = firestore().collection('Collection').doc().collection('subcollection');
            query = query.where('act', '==', 1);
            query = query.where('city', '==', this.state.selected_city);
            query = query.orderBy('update_time', 'desc');
            query = query.limit(10);

            query.onSnapshot({
                error: (e) => this.setState({ errorMessage: e, refreshingPatients: false }),
                next: (querySnapshot) => {
                    var dataSource = querySnapshot.docs.map(doc => { return { ...doc.data(), doc_id: doc.id } });                       
                    var lastVisiblePatient = dataSource[dataSource.length - 1].doc_id;
                    this.setState({
                        dataSource: dataSource,
                        lastVisiblePatient: lastVisiblePatient,
                        refreshingPatients: false,
                    });
                },
            });
    }
 }
编辑:添加了示例代码。我想一直听Firestore DB的变化。这是正确的做法吗?如果是,它是如何工作的,因为
componentDidMount
只被调用一次?
注意:我只在screen state设置为7时收听Firestore。

您的
组件didmount
实际上只调用一次,但您在其中附加了一个永久侦听器。因此,您在onSnapshot.next中指定的处理程序将立即与数据库中的初始数据一起调用,之后每次匹配查询的数据发生更改时都会调用该处理程序。

解决方案1: 阅读代码中的注释

componentDidUpdate(prevState, prevProps) {
  if(prevState !== this.state.screen && this.state.screen === 7) {

        var query = firestore().collection('Collection').doc().collection('subcollection');
            query = query.where('act', '==', 1);
            query = query.where('city', '==', this.state.selected_city);
            query = query.orderBy('update_time', 'desc');
            query = query.limit(10);

            query.onSnapshot({
                error: (e) => this.setState({ errorMessage: e, refreshingPatients: false }),
                next: (querySnapshot) => {
                    var dataSource = querySnapshot.docs.map(doc => { return { ...doc.data(), doc_id: doc.id } });                       
                    var lastVisiblePatient = dataSource[dataSource.length - 1].doc_id;
                    this.setState({

                    // you are not updating screen so it is always 7
                    // if you update other state variables, it will trigger ComponentDidUpdate again, 
                    // and again and again and again

                        dataSource: dataSource,
                        lastVisiblePatient: lastVisiblePatient,
                        refreshingPatients: false,
                    });
                },
            });
    }
 }
通过添加
prevState!==在这个.state.screen
,您可以防止每次更新其他状态时触发
componentDidUpdate

如dataSource、lastVisiblePatient和refreshingPatients

解决方案2:因为您使用的是类组件,所以可以使用setState回调

this.setState({screen: newValue}, doSomethingNew);

doSomethingNew(){
     if (this.state.screen === 7) {
         // your code goes here
     }
}
使用
newValue
更新
screen
值后,将触发回调函数(此处为
doSomethingNew

解决方案3:如果转换为函数组件,则可以使用
useffect
依赖项

const [screen, setScreen] = useState(initialValue);    
useEffect(() => {
    if (screen === 7) {
        //do something here
    }
}, [screen]);    // adding screen as a dependency means this  useEffect is triggered only when screen value is changed.

也许你可以编辑这个问题来展示你感到困惑的代码的例子?别让我们猜你在说什么。请务必查找可能会注销侦听器的类似代码。@DougStevenson抱歉,我刚刚编辑并添加了一个示例代码。如果问题还不清楚,请告诉我。是的,componentDidUpdate是一个不错的选择。您是否使用其他位置的一些值设置初始状态?@O.O当应用程序启动时,我将状态设置为0,稍后我将状态设置为7,因此显然,
componentDidMount
中的代码从不从db获取。啊哈!所以,我实际上可以从其他任何地方用该侦听器代码调用函数,并且该侦听器将永久处于活动状态,对吗?我不确定我是否正确理解了您的注释。我想把连接监听器的代码(
query.onSnapshot({…})
)移动到一个函数中,然后从
componentDidMount
调用它,那么它的工作原理就完全一样了。我的意思是,如果我不是从
componentDidMount
调用它,而是从另一个函数调用它呢?这取决于其他函数是什么,如果已经调用了该函数。我建议阅读本文,了解React中的组件生命周期,以及在什么时候自动调用组件的哪些方法。是。顺便说一下:如果你是新手,我建议你试试。你已经有了大部分的代码,它会教你更多的东西,并且比我们在这里能做的更快得到答案。这些是一些很好的解决方案,谢谢!然而,看看上面@Frank van Puffelen所说的,他说听众是永久性的,所以一旦它被调用,它将永久性地倾听。这意味着我甚至不必使用任何
componentDidMount
componentdiddupdate
。至少我是这样理解的。那么为什么要添加
这个.state.screen===7
?因为我不希望在ex.user只访问过屏幕1、2或3等时调用该侦听器。我希望仅当用户进入屏幕7并从那时起继续侦听时才调用它。然后,您需要一个
组件diddupdate
-当
屏幕===7
时,您将添加一个永久侦听器,并且由于您不再需要侦听器,因此必须添加一个标志变量,以便以后不必再创建另一个侦听器。假设用户首先选择7,然后再次选择3和7。不能再次单击按钮吗?如果用户再次单击,它将打开另一个侦听器。。。