0

I’m building a React form that will have several drop-down boxes populated with data from MongoDB. I’m relatively new to React and a beginner with MongoDB.

I’m starting with just trying to create a basic page with one drop-down on it. Once I get that right, I can move on to adding the other drop-downs.

I’ve been able to successfully get the data into the drop-down by just cramming all of the code into one file. Now, I’m trying to start refactoring the code by properly splitting pieces into separate files. And that’s where I’m running into problems.

I’ve split out my MongoDB data pull (using Mongo Stitch) into a separate “service” file. And I’m still getting data through that new service file. But when I then try to pull that service-file data into my main (App.js) page, I’m getting a “Cannot read property 'data' of undefined” error. So, clearly, the way I’m trying to pull the data into my App.js file is wrong. I’d appreciate any expert insights anyone could offer!

Here’s my App.js file –

import React, { Component } from "react";
import "./App.css";
import { getProjects } from "./services/svcProjects";

class App extends Component {
  state = {
    data: {
      selProject: ""
    },
    Projects: []
  };

  async componentDidMount() {
    await this.fetchProjects();
  }

  async fetchProjects() {
    const { data: projects } = await getProjects();
    console.log(projects);
    this.setState({ projects });
  }

  render() {
    return (
      <div className="App">
        <h1>Project Log</h1>
        <label htmlFor={"selProject"}>{"Project"}</label>
        <select name={"selProject"} id={"selProject"} className="form-control">
          <option value="" />
          {this.state.projects.map(a => (
            <option key={a._id} value={a.project}>
              {a.project}
            </option>
          ))}
        </select>
      </div>
    );
  }
}

export default App;

And here’s the “projects service” file. Again, please note that the console.log statements here show that I’m still getting data back from MongoDB. I’m just not pulling the data into my App.js file the right way.

Also, by the way, I realize that having my Mongo connection info in this file is a huge security hole. I’ll be fixing that later.

import {
  Stitch,
  RemoteMongoClient,
  AnonymousCredential
} from "mongodb-stitch-browser-sdk";

export function getProjects() {
  const client = Stitch.initializeDefaultAppClient("------");
  const db = client
    .getServiceClient(RemoteMongoClient.factory, "-----")
    .db("----------");
  client.auth
    .loginWithCredential(new AnonymousCredential())
    .then(() =>
      db
        .collection("--------")
        .find({}, { sort: { Project: 1 } })
        .asArray()
    )
    .then(res => {
      console.log("Found docs", res);
      console.log("[MongoDB Stitch] Connected to Stitch");
      return res;
    })
    .catch(err => {
      console.error(err);
    });
}
1
  • Quick look at your code, you’re setting projects with a capital P in your this.setState Commented Jan 13, 2019 at 23:10

2 Answers 2

1

It looks like you're using destructuring to get the data member from an object returned by getProjects(), but getProjects() doesn't return an object with such a member.

Perhaps you'd like to change it to something like the following -

async fetchProjects() {
  const projects = await getProjects();
  console.log(projects);
  this.setState({ projects });
}

Also, like @Win mentioned, the P in projects is capitalized in your state initialization but not afterwards. You might wanna fix that.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the suggestion, tkore! I made the change you recommended, and I think I'm making progress. I'm now getting an error of "Cannot read property 'map' of undefined". So, it looks like it's now passing the data on through, but just not able to execute the map method. Any thoughts on next steps?
@JoelMorgan great, glad I could be of help. Regarding your 2nd issue - it happens because at the time you're running the code, this.state.projects isn't recognized as an array. replacing your capital P in your state initialization should solve it.
If it doesn't get solved, just use (this.state.projects || []).map to fall back to an empty array if this.state.projects is undefined
0

I've discovered that my problem boils down to the fact that my data isn't arriving in the componentDidMount lifecycle hook soon enough. So, by the time the process moves on, the "projects" data is still undefined. In other words, my "async / await" isn't . . . awaiting!

I'll be posting a separate question about how I can make that async wait until I actually get the data back. But again, just wanted to mark this as "solved" because the problem isn't happening downstream from the data fetch. The data simply isn't arriving soon enough.

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.