Как Firestore onSnapshot прослушивает изменения в React-Native? - PullRequest
1 голос
/ 20 апреля 2020

Я видел в нескольких местах людей, размещающих код слушателя внутри 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 все время. Это правильный способ сделать это? Если да, то как это работает, потому что componentDidMount вызывается только один раз? Примечание: я слушаю Firestore, только когда состояние экрана установлено на 7.

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

Solution1: Прочитайте комментарий внутри кода.

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.

Solution3: Если вы преобразуете в компонент функции, вы можете использовать зависимость 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.
1 голос
/ 20 апреля 2020

Ваш componentDidMount действительно вызывается только один раз, но вы подключаете туда постоянный слушатель. Таким образом, обработчик, который вы указываете в onSnapshot.next, вызывается сразу с начальными данными из базы данных, и после этого каждый раз, когда изменяются данные, соответствующие запросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...