How does a Firestore onSnapshot listens for changes in React-Native?

|▌冷眼眸甩不掉的悲伤 提交于 2020-05-30 07:56:10

问题


I have seen in multiple places people placing the listener code inside the componentDidMount, however, I am wondering how does it work since componentDidMount is called only once, therefor, it should fetch only once. How does it fetches again when changes happen in Firestore?

Example code :

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,
                    });
                },
            });
    }
 }

EDIT: added an example code. I want to listen to changes of Firestore DB all the time. Is that the correct way of doing it? If yes, how does it work because componentDidMount is only called once? Note: I am only listening to Firestore when screen state is set to 7.


回答1:


Your componentDidMount is indeed only called once, but you're attaching a permanent listener in there. So the handler that you specify in onSnapshot.next is called right away with the initial data from the database, and after that each time that the data matching the query changes.




回答2:


Solution1: Read the comment inside the code.

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,
                    });
                },
            });
    }
 }

By adding prevState !== this.state.screen, you can prevent componentDidUpdate being triggered everytime you update other states.

Like dataSource, lastVisiblePatient, and refreshingPatients.

Solution 2: Since you are using class components, you can use setState callback.

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

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

the callback function(here doSomethingNew) is triggered after screen value is updated with newValue.

Solution3: If you convert to function component, you can use useEffect dependency.

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.


来源:https://stackoverflow.com/questions/61314627/how-does-a-firestore-onsnapshot-listens-for-changes-in-react-native

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!