Reputation: 5
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);
});
}
Upvotes: 0
Views: 2018
Reputation: 5
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.
Upvotes: 0
Reputation: 1151
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.
Upvotes: 1