1

i'm new to react and i'm playing around to see how the basic concepts work. I'm trying to render at list with data from a firebase server, the deta gets fetched ok but i'm having trouble rendering it in my listitem component.

Parent Component:

class App extends Component {
  state = {
    data: null as null | Data[]
  }
  componentDidMount() {
    this.getData();
  }

  private getData(): void {
    let _data = new Array < Data > ()
    const db = firebase.firestore();
    db.collection('data').get()
      .then(snapshot => {
        snapshot.docs.forEach(doc => {
          let data: Data = {
            id: doc.id,
            name: doc.data().name,
            description: doc.data().description,
            country: doc.data().country,
            town: doc.data().town,
            lat: doc.data().lat,
            long: doc.data().long,
            created: doc.data().created,
            updated: doc.data().updated,
            img: doc.data().img
          }
          _data.push(data)
        })
      })
    this.setState({
      data: _data
    })
  }



  render() {
    let list = null;
    if (this.state.data) {
      list = ( 
      <div > {
          this.state.data.map(d => {
            return <ListObject name = {d.name} />
          })
        } </div>
      )
    }
    return ( 
      <div>
        <p> List </p>
        {list}
      </div>
    )
  }
}

export default App;

Child Component:

import React from 'react'
import './ListObject.css';

const listObject = (props: any) => {
    return (
        <div className="ListObject">
            <p>i Am {props.name}</p>
        </div>
    )
};

export default listObject;

What am i doing wrong here? The ListObject component works outside of the iteration.

2 Answers 2

2

That's because db.collection('data').get() asynchronously run so that in your code, state haven't been set:

let _data = [];
db.collection('data').get().then(function() {
   _data.append();
});
this.setState({
    data: _data
})

there is no data in _data.

So to get rid of this, you could use synchronous loop for ... of, and make the code a bit easier to read like so:

private getData(): void {
    const db = firebase.firestore();
    db.collection('data').get()
      .then(snapshot => {
         let _data = new Array < Data > ()
         for (let doc of snapshot.docs) {
            let data: Data = {
                id: doc.id,
                name: doc.data().name,
                description: doc.data().description,
                country: doc.data().country,
                town: doc.data().town,
                lat: doc.data().lat,
                long: doc.data().long,
                created: doc.data().created,
                updated: doc.data().updated,
                img: doc.data().img
            }
            _data.push(data);
         }
         this.setState({
             data: _data
         });
      })
  }

and your render:



render() {
    let list = (this.state.data || []).map(d => {
        return <ListObject name = {d.name} />
    });

    return ( 
        <div>
            <p> List </p>
            <div>{list}</div>
        </div>
    )
}
Sign up to request clarification or add additional context in comments.

2 Comments

yeah sorry the dogparks was a typo that i have fixed now.
Sorry, my bad.. it's supposed to be inside render function.
1

Because dogparks is null.

Also you should create list outside of your render method.

So like:

let list = (this.state.data || []).map(d => {
    return <ListObject name = {d.name} />
});

render() {
    return ( 
      <div>
        <p> List </p>
        <div>{list}</div>
      </div>
    )
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.