Рендеринг данных из Firebase в React - PullRequest
0 голосов
/ 27 ноября 2018

Пожалуйста, помогите мне с рендерингом данных, извлеченных из базы данных Firebase Realtime.

Я успешно извлек данные из Firebase в виде массива.Следующим шагом является отображение данных - здесь начинается проблема.

Данные, которые я хочу отобразить, должны храниться в состоянии «модулей».Сначала он устанавливается как пустой массив.Затем данные извлекаются, состояние обновляется с помощью setState в методе жизненного цикла CoumponentDidMount - я могу видеть данные в виде массива в моем React DevTool - но компонент не отображает (отображает) их.

Я полагаю, что проблема имеетчто-то связанное с методами жизненного цикла, потому что я могу регистрировать состояние в консоли, но я также вижу всплывающую информацию о том, что массив (полученный из Firebase) «был оценен только сейчас».Если я прав, это значит, что данные извлекаются после метода рендеринга?Что мне делать, чтобы решить проблему и правильно отобразить данные?

Вот мой код:

    import React, { Component } from "react";
import firebase from "firebase";
import { DB_CONFIG } from "./database/db_config";
import ModulesData from "./modulesData";
//import LandingPage from "./components/landingPageComponents/landingPage";
import ThematicAreaNav from "./components/navbarComponents/thematicAreaNav";
import ThematicArea from "./components/singleModuleComponents/thematicArea";
import OrderList from "./components/orderListComponents/orderList";
import Footer from "./components/footerComponents/footer";

let chosenModulesArray = [];

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      holdClickedModulesNames: chosenModulesArray,
      modules: []
    };
  }

  componentDidMount() {
    let ref = firebase
      .initializeApp(DB_CONFIG)
      .database()
      .ref();

    ref.once("value").then(dataSnapshot => {
      this.response = dataSnapshot.val()["modulesData"];
      this.setState({ modules: this.response });
    });
  }

  render() {
    return (
      <div>
        {console.log(this.state.modules)}}{/*<LandingPage />*/}
        <ThematicAreaNav modules={this.state.modules} />
        <div className="main-layout">
          <ThematicArea
            modules={this.state.modules}
            orderedModules={this.props.orderedModules}
            clickedModuleNames={this.state.holdClickedModulesNames}
            chosenModulesNames={this.state.holdClickedModulesNames}
          />

          <OrderList
            clickedModuleNames={this.state.holdClickedModulesNames}
            chosenModulesNames={this.state.holdClickedModulesNames}
          />
        </div>
        <div className="footer">
          <Footer />
        </div>
      </div>
    );
  }
}

export default App;

enter code here

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

С визуальной точки зрения Если ваши данные возвращаются после render(), вместо того, чтобы показывать пустой экран или наполовину заполненный компонент, покажите окно загрузки, ожидающее заполнения ваших данных - этовсегда хорошая практика с точки зрения UX!

Пример кода:

class app extends Component {
    constructor(props){
        modules:null,
        loading:true,
    }

    componentDidMount(){
        getModules();
    }
    getModules(){
        let ref = firebase
         .initializeApp(DB_CONFIG)
         .database()
         .ref();

        ref.once("value").then(dataSnapshot => {
          this.response = dataSnapshot.val()["modulesData"];
          //once the data is back, set the loading to false so it can be rendered
          this.setState({ data: this.response, loading: false });
        });
    }
    render(){
        // deconstruct 'modules' from the state to call it without this.state...
        const {modules, loading, holdClickedModulesNames} = this.state;
        const { orderedModules } = this.props;
        return loading ? (
            <div>
                loading...
            </div>
        ) : (
            <div>
              <ThematicAreaNav modules={modules} />
              <div className="main-layout">
                <ThematicArea
                  modules={modules}
                  orderedModules={orderedModules}
                  clickedModuleNames={holdClickedModulesNames}
                  chosenModulesNames={holdClickedModulesNames}
                />

                <OrderList
                  clickedModuleNames={holdClickedModulesNames}
                  chosenModulesNames={holdClickedModulesNames}
                />
              </div>
              <div className="footer">
                <Footer />
              </div>
            </div>
        )
    }
}
0 голосов
/ 27 ноября 2018

Поскольку вы пытаетесь выполнить асинхронное действие в методе componentDidMount().Вы можете использовать async await:

async componentDidMount() {
    let ref = await firebase
      .initializeApp(DB_CONFIG)
      .database()
      .ref();

    const firebaseResponse = await ref.once("value");

    this.response = firebaseResponse.val()["modulesData"];
    this.setState({ modules: this.response });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...