2

I have a React component that connects to Firebase to receive data. I'm able to connect and get the data I'd like to use to log out to the console, but I'm unable to return it with HTML. In fact, the HTML returns "01". Can anyone tell me why the data is showing up in the console but not the page, and the 01 is being displayed in the browser?

/* eslint-disable */
import React, { Component } from "react";
import firebase from "./Firebase";
class ActiveProjects extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoaded: false,
      projects: []
    };
  }
  componentDidMount() {
    const db = firebase.firestore();
    db.collection("projects")
      .get()
      .then(querySnapshot => {
        const data = querySnapshot.docs.map(doc => doc.data());
        data.forEach(cur_doc => {
          this.state.projects.push({ ...cur_doc });
        });
      })

      .then(result => {
        this.setState({ isLoaded: true });
      });
  }

  render() {
    const { isLoaded, projects } = this.state;
    if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <div>
          {Object.keys(
            projects.map((proj, index) => (
              <div>
                <h2>{proj["description"]}</h2>
                {console.log(index)}{console.log(proj["description"])} 
                //Output 
                // 0 
                // This is some text for the description. 
                // 1 
                // My description text.
              </div>
            ))
          )}
        </div>
      );
    }
  }
}
export default ActiveProjects;

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Andrew
  • 21
  • 1
  • What were you trying to print under the `h2` tag? – Brian Thompson Mar 16 '20 at 18:33
  • 1
    [`this.state.projects.push` is mutating the state. Don't do that.](https://stackoverflow.com/q/37755997/1218980) [Replace the state with a new array instead.](https://stackoverflow.com/q/26253351/1218980) – Emile Bergeron Mar 16 '20 at 18:39
  • @BrianThompson I'm trying to print the contents of proj["description"] , which successfully logs out to the console. However, the HTML displays "01", despite using the same code in both the log and the HTML. – Andrew Mar 16 '20 at 18:40
  • 1
    So this is the exact code you run when you get the `01` printed to the page? – Brian Thompson Mar 16 '20 at 18:40

3 Answers3

1

The problem is you are unnecessarily using Object.keys before mapping over the state array. Remove this.

Object.keys(projects) is taking your array and making a new one with the keys as it's values. Since the keys in an array are the indexes, your values become [0,1].

Example:

const myArray = ['value1', 'value2'];

console.log(Object.keys(myArray))

You are rendering the output of Object.keys so no matter what you do inside the mapping function, it will always return an array of indexes.

Secondly, as @EmileBergeron pointed out, you are mutating state. This doesn't appear to be directly causing your issue, but it needs to be fixed.

To fix, change to this:

const data = querySnapshot.docs.map(doc => doc.data());
this.setState({ projects: data });

The forEach doesn't seem necessary since you're using all of the values without changing anything. Setting state to data should be equivalent.

Brian Thompson
  • 13,263
  • 4
  • 23
  • 43
  • 1
    Great answer! Additional improvement for OP: do both state changes in one go, `this.setState({ isLoaded: true, projects: data })`. – Emile Bergeron Mar 16 '20 at 18:52
0

I think using projects.description should do the job better and as well get rid of the unnecessary objects.keys

codemon
  • 62
  • 4
0

Thank you @EmileBergeron @codemon @BrianThompson! The code below achieved the desired result.

/* eslint-disable */
import React, { Component } from "react";
import firebase from "./Firebase";
class ActiveProjects extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoaded: false,
      projects: []
    };
  }
  componentDidMount() {
    const db = firebase.firestore();
    db.collection("projects")
      .get()
      .then(querySnapshot => {
        const data = querySnapshot.docs.map(doc => doc.data());
        this.setState({ isLoaded: true, projects: data });
      });
  }

  render() {
    const { isLoaded, projects } = this.state;
    if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <div>
          {projects.map((project, index) => (
            <h2>{project.description}</h2>
          ))}
        </div>
      );
    }
  }
}
export default ActiveProjects;

Andrew
  • 21
  • 1