Why is my state showing up in my console logs but not my HTML?

Viewed 46

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;

3 Answers

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.

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

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;

Related