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

时间:2020-04-20 03:19:25

标签: javascript firebase react-native google-cloud-firestore

我已经在很多地方看到人们将侦听器代码放在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仅被调用一次? 注意:我仅在屏幕状态设置为7时收听Firestore。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

解决方案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 !== this.state.screen,可以防止每次更新其他状态时都触发componentDidUpdate

像dataSource,lastVisiblePatient和refreshingPatients。

解决方案2:由于您使用的是类组件,因此可以使用setState回调。

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

doSomethingNew(){
     if (this.state.screen === 7) {
         // your code goes here
     }
}

在使用doSomethingNew更新了screen值之后触发了回调函数(此处为newValue)。

解决方案3::如果转换为功能组件,则可以使用useEffect依赖项。

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.