realph realph - 3 months ago 13
React JSX Question

React: Pass Firebase Data Down Via Props

I'm trying to pass some Firebase data down from one component via

props
to another component, but it doesn't seem to be letting me iterate over the Firebase data in the child component.

App.js

class App extends Component {
constructor(props) {
super(props);
this.state = {
games: []
};
}

componentDidMount() {
const gamesRef = firebase.database().ref('games').orderByKey();

gamesRef.once('value', snap => {
snap.forEach((childSnapshot) => {
this.state.games.push(childSnapshot.val());
})
})
}

render() {
return (
<div className="App">
<Games data={ this.state.games } />
</div>
);
}
}


Games.js

class Games extends Component {
componentDidMount() {
console.log(this.props.data); // this logs successfully
}

render() {
return (
<div className="container">
<div className="Games flex flex-end flex-wrap">
{ this.props.data.map(function (game, i) {
return (
<h1>{ game.title }</h1>
)
}) }
</div>

</div>
);
}
}


For some reason I'm having a problem when trying to
map()
over my
props.data
. It's definitely being passed down to my
Games
component, because it's printing the
console.log(this.props.data)
to the console with the data it gets back from Firebase.

Do I have to wait for my Firebase data to resolve before mapping over it, and if so how do I do this?

Any help is appreciated. Thanks in advance!

Answer

I think the problem lies with your componentDidMount in your App class. You're updating state with

this.state.games.push(childSnapshot.val());

You shouldn't do that. State should only be updated with this.setState (or at the very least you should use this.forceUpdate()), as otherwise it will not re-render. I would instead advise doing

componentDidMount() {
  const gamesRef = firebase.database().ref('games').orderByKey();
  let newGames;

  gamesRef.once('value', snap => {
    snap.forEach((childSnapshot) => {
      newGames.push(childSnapshot.val());
    })
  })

  this.setState({games: newGames});
}

This will cause a re-render of the App component, causing the new data to be passed as a prop to the Games component.