Я должен нажать кнопку дважды, чтобы заполнить состояние реакции из базы данных Firebase в реальном времени - PullRequest
0 голосов
/ 11 декабря 2018

В моем компоненте реакции, когда компонент монтируется, я хочу запустить функцию loadData (), чтобы заполнить массив объектов людей в состоянии.

Этот компонент называется UserDisplaySection.js

componentDidMount() {
    this.loadData();
}

, который вызывает функцию для загрузки данных:

loadData = () => {
    const db = fire.database();
    const ref = db.ref('User');

    let currentState = this.state.people;
    ref.on('value', (snapshot) => {
      snapshot.forEach( (data) => {
        const currentStudent = data.val();
        let user ={
          "email" : currentStudent.Email,
          "name": currentStudent.Name,
          "age": currentStudent.Age,
          "location": currentStudent.Location,
          "course": currentStudent.Course,
          "interests": currentStudent.Interests
        }
        currentState.push(user);

      });
    });

    this.setState({
      people: currentState
    });

  }

Из другого компонента, называемого Home.js, я отображаю UserDisplaySection.js с переключателем кнопки, которая устанавливает состояние логического значения willDisplayUser, которое по умолчанию инициализируется как false.

handleDisplayUsers = e => {
    e.preventDefault();
    this.setState({
      willDisplayUsers: !(this.state.willDisplayUsers),

    });
  }

    render() {
        return (
          <div>
            <button className="mainButtons" onClick={this.handleDisplayUsers}>View Users</button> <br />
            {this.state.willDisplayUsers ? <UserDisplaySection/>: null}

          </div>
        );

  }

Примечание: функция работает и заполняет состояние правильными данными, но толькопосле того, как я рендерил компонент UserDisplaySection.js во второй раз и работал отлично, пока я не перезагрузил страницу

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Корень проблемы в том, что вы устанавливаете состояние за пределами обратного вызова ref.on.

Выборка данных асинхронная, и обратный вызов будет выполнен позже во времени.Поскольку установленное состояние находится за пределами обратного вызова, оно вызывается сразу после регистрации прослушивателя, но до завершения выборки данных.Вот почему он не работает при начальном рендеринге / нажатии кнопки: он показывает начальное состояние, не дожидаясь окончания выборки.

Кроме того, использование once вместо on может лучше подойти для вашего случая.

loadData = () => {
    const db = fire.database();
    const ref = db.ref('User');

    let currentState = this.state.people;
    ref.once('value', (snapshot) => {
      // callback start
      snapshot.forEach( (data) => {
        const currentStudent = data.val();
        let user ={
          "email" : currentStudent.Email,
          "name": currentStudent.Name,
          "age": currentStudent.Age,
          "location": currentStudent.Location,
          "course": currentStudent.Course,
          "interests": currentStudent.Interests
        }
        currentState.push(user);
      });

      this.setState({
        people: currentState
      });
      // callback end
    });

    // setState used to be here, outside of the callback
  }
0 голосов
/ 11 декабря 2018

Делая ref.on(), вы фактически объявляете слушателя, который «прослушивает изменения данных в определенном месте», как объяснено в doc .«Обратный вызов будет инициирован для исходных данных и снова при каждом изменении данных».Другими словами он отключен от вашего события кнопки onClick.

Если вы хотите получать данные по требованию, то есть, когда нажимается ваша кнопка, вы должны использовать вместо этого метод once(), который "прослушивает ровно одно событие указанного типа события, а затем перестает слушать ".

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