Reputation: 197
Please, help me with rendering data retrived from Firebase Realtime Database.
I succefully retrived data frome Firebase as an array. Next step is to display the data - here the problem begins.
The data I want to display should be stored in "modules" state. At first, it's set as an empty array. Then data are retrived, state is updated by setState in CoumponentDidMount lifecycle method - I can see the data as an array in my React DevTool - but component is not rendering (displaying) them.
I suppose that a propblem has something to do with lifecycle methods, because I can log the state in the console, but I can also see a pop-up info that the array (retrived from Firebase) "was evaluated just now". If I'm right, it means that the data are retrived after render method? What shall I do, to solve the problem and diplay data properly?
Here is my code:
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
Upvotes: 2
Views: 2221
Reputation: 501
From a visual perspective
If your data is being returned after render()
, rather than showing a blank screen or half populated component, show a loading screen whist waiting for your data to be populated - this is always good practice from a UX perspective!
Code example:
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>
)
}
}
Upvotes: 2
Reputation: 2375
Bcoz you're trying to perform an asynchronous action within the componentDidMount()
method. You can use 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 });
}
Upvotes: 1