Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

APIs

Killeon Patterson
Killeon Patterson
18,528 Points

Rendering a change in data (MERN App)

I'm working on a project that creates a basic MERN application. The interface allows a client to enter a message into an input field, press a button, and then display that message to the client along with a newly created id.

// client/src/App.js;
import React, { Component } from "react";
import axios from 'axios';
import './App.css';

class App extends Component {
  // initialize our state
  state = {
    data: [],
    id: 0,
    message: null,
    intervalIsSet: false,
    idToDelete: null,
    idToUpdate: null,
    objectToUpdate: null
  };

// when component mounts, first thing it does is fetch all existing data in our db
// then we incorporate a polling logic so that we can easily see if our db has
// changed and implement those changes into our UI

componentDidMount() {
    this.getDataFromDb();
    if (!this.state.intervalIsSet) {
      let interval = setInterval(this.getDataFromDb, 1000);
      this.setState({ intervalIsSet: interval});
    }
}
// never let a process live forever
// always kill a process everytime we are done using it
componentWillUnmount() {
  if (this.state.intervalIsSet) {
    clearInterval(this.state.intervalIsSet);
    this.setState({ intervalIsSet: null });
  }
}

// just a note, here, in the front end, we use the id key of our data object
// in order to identify which we want to Update or delete.
// for our back end, we use the object id assigned by MongoDB to modify
// data base entries

// our first get method that uses our backend api to
// fetch data from our data base
getDataFromDb = () => {
  fetch("http://localhost:3001/api/getData")
    .then(data => data.json())
    .then(res => this.setState({ data: res.data}));
  };

  //our put method that uses our backend api
  //to create new query into our data base
  putDataToDB = message => {
    let currentIds = this.state.data.map(data => data.id);
    let idToBeAdded = 0;
    while (currentIds.includes(idToBeAdded)) {
        ++idToBeAdded;
    }

    axios.post("http://localhost:3001/api/putData", {
      id: idToBeAdded,
      message: message

    });
  };

// our delete method that uses our backend api
// to remove existing database information
deleteFromDB = idTodelete => {
  let objIdToDelete = null;
  this.state.data.forEach(dat => {
      if (dat.id === idTodelete) {
        objIdToDelete = dat._id;
      }
  });

    axios.delete("http://localhost:3001/api/deleteData", {
      data: {
        id: objIdToDelete

      }
    });
};

// our update method that uses our backend api
// to overwrite existing data base information
      updateDB = (idToUpdate, updateToApply) => {
        let objIdToUpdate = null;
        this.state.data.forEach(dat => {
          if (dat.id === idToUpdate) {
            objIdToUpdate = dat._id;
          }
        });

        axios.post("http://localhost:3001/api/updateData", {
          id: objIdToUpdate,
          update: { message: updateToApply }
        });
      };

  // here is our UI
  // it is easy to understand their functions when you
  // see them render into our screen
  render() {
    const { data } = this.state;
    return (
      <div>
        <ul>
          {data.length <= 0
            ? "NO DB ENTRIES YET"
            : data.map(dat => (
                <li style={{ padding: "10px" }} key={data.message}>
                  <span style={{ color: "gray" }}> id: </span> {dat.id} <br/>
                  <span style={{ color: "gray" }}> data: </span>
                  {dat.message}
                </li>
              ))}
        </ul>
        <div style={{ padding: "10px" }}>
          <input
            type="text"
            onChange={e => this.setState({ message: e.target.value })}
            placeholder="add something in the database"
            style={{ width: "200px" }}
          />
          <button onClick={() => this.putDataToDB(this.state.message)}>
            ADD
          </button>
        </div>
        <div style={{ padding: "10px" }}>
          <input
            type="text"
            style={{ width: "200px" }}
            onChange={e => this.setState({ idToDelete: e.target.value })}
            placeholder="put id of item to delete here"
          />
          <button onClick={() => this.deleteFromDB(this.state.idToDelete)}>
            DELETE
          </button>
        </div>
        <div style={{ padding: "10px" }}>
          <input
            type="text"
            style={{ width: "200px" }}
            onChange={e => this.setState({ idToUpdate: e.target.value })}
            placeholder="id of item to update here"
          />
          <input
            type="text"
            style={{ width: "200px" }}
            onChange={e => this.setState({ updateToApply: e.target.value })}
            placeholder="put new value of the item here"
          />
          <button
            onClick={() =>
              this.updateDB(this.state.idToUpdate, this.state.updateToApply)
            }
          >
            UPDATE
          </button>
        </div>
      </div>
    );
  }
}

export default App;

The buttons are successfully posting to MongoDB:Atlas and can be deleted from the cloud. Although, the app begins with a display to the client "NO DB ENTRIES YET". After the client enters information that display is supposed to show the message, along with an id. 
And it doesn't. I'd appreciate some insight if you have any.

``react``
<ul>
          {data.length <= 0
            ? "NO DB ENTRIES YET"
            : data.map(dat => (
                <li style={{ padding: "10px" }} key={data.message}>
                  <span style={{ color: "gray" }}> id: </span> {dat.id} <br/>
                  <span style={{ color: "gray" }}> data: </span>
                  {dat.message}
                </li>
              ))}
        </ul>

2 Answers

getDataFromDb = () => {
  fetch("http://local:3001/api/getData")
    .then(data => data.json())
    .then(res => this.setState({ data: res.data}));
  };

Double Check the url where you are fetching but I think you might have a typo and it should be localhost:3001 and since the fetching is failing the data array in your state never gets updated and thus your conditional rendering is always showing "NO DB ENTRIES YET"

Killeon Patterson
Killeon Patterson
18,528 Points

Hello Juan,

Thank you for your reply. There was a typo with the fetch method. I made the edit to "local:3001" to "localhost:3001." Although, now it's making endless calls to resource, not giving the chance to modify anything, and causing 304 responses in the console.

My intended logic for the loop appears to have the correct syntax?

i think the problem is here: const { data } = this.state; i think this distructured object should not be constant.