编辑:可以在此处找到项目存储库的链接。
当我的个人资料页面在我的 React 应用程序中加载时,我正在尝试获取数据。 我的客户端在我的本地主机:3000上运行,服务器运行在本地主机:5000上。
我在客户端文件夹的package.json中也有一个代理,将其指向localhost:5000(据说(。 在我的服务器文件中,我也有cors,以及我过去使用过的所有常用的花里胡哨的东西。
每当我的组件挂载时,在我的控制台中我都会收到一个 404 错误,说我的 GET 请求失败,它说它试图到达 localhost:3000/recipes - 根据我的代理,这是错误的,因为它应该向 localhost:5000 发出请求。
但是,它变得更加棘手,因为为了测试它,我将路由更改并硬编码为 localhost:5000,但即使这样也返回了 404 错误。
起初我认为我的后端 GET 请求逻辑有问题,但问题是,当我在 componentDidUpdate(( 中粘贴发出 get 请求的相同函数时,它成功获取所有配方(它是一个食谱应用程序(,只是它触发了一个无限循环并发疯了,显然我不能拥有它。
有人知道这是怎么回事吗?为什么我的 getRecipes(( 函数(发出 get 请求(在 componentDidMount(( 中不起作用,收到 404 错误,没有成功代理,但随后在 componentDidUpdate(( 中工作?为什么是无限循环?
这是我的前端代码:
import React, { Component } from "react";
import {
Button,
Modal,
ModalHeader,
ModalBody,
Form,
FormGroup,
Label,
Input
} from "reactstrap";
import styles from "./RecipeList.module.css";
// import { addRecipe } from "../RecipeFunctions/RecipeFunctions";
import axios from "axios";
import RecipeItem from "../RecipeItem/RecipeItem";
import jwt_decode from "jwt-decode";
export default class RecipeList extends Component {
state = {
recipes: [],
modal: false,
email: "",
recipeName: "",
ingredients: "",
directions: "",
errors: {
msg: ""
}
};
toggle = () => {
this.setState({
modal: !this.state.modal
});
};
onChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
onSubmit = e => {
e.preventDefault();
const newRecipe = {
user_email: this.state.email,
title: this.state.recipeName,
ingredients: this.state.ingredients,
directions: this.state.directions
};
// Make Post Request w/ Axios from RecipeFunctions.js
this.addRecipe(newRecipe);
this.getRecipes();
};
getRecipes = () => {
axios.get(`/recipes/${this.state.email}`).then(res => {
this.setState({
recipes: res.data
});
});
};
addRecipe = newRecipe => {
axios.post("/recipes", newRecipe).then(response => {
console.log("Recipe added.");
console.log(this.state.email)
});
};
deleteRecipe = id => {
axios
.delete(`/recipes/${id}`)
.then(this.getRecipes())
.catch(err => console.log(err));
};
viewRecipe = id => {
axios
.post(`/viewrecipe/${id}`)
.then(this.getRecipes())
.catch(err => console.log(err));
};
closeRecipe = id => {
axios
.post(`/closerecipe/${id}`)
.then(this.getRecipes())
.catch(err => console.log(err));
};
componentDidMount() {
try {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
this.setState({
firstname: decoded.firstname,
lastname: decoded.lastname,
email: decoded.email
});
} catch {
this.setState({
errors: {
msg: "You must be logged in to see your profile."
}
});
}
this.getRecipes();
}
render() {
if (this.state.email) {
return (
<div id={styles.compWrapper} className="container">
<div>
<div id={styles.titleWrapper} className="col-sm-8 mx-auto">
<h1 className="text-center">{this.state.firstname}'s Cookbook</h1>
</div>
<div className="text-center">
<div>
<Button
id={styles.addRecipeBtn}
outline
color="secondary"
onClick={this.toggle}
size="sm"
>
Add Recipe
</Button>
<div className={styles.feedWrapper}>
<Modal
className={styles.addRecipeModal}
isOpen={this.state.modal}
toggle={this.toggle}
>
<ModalHeader toggle={this.toggle}>New Recipe</ModalHeader>
<ModalBody>
<Form onSubmit={this.onSubmit}>
<FormGroup>
<Label for="item">Recipe Name</Label>
<Input
type="text"
name="recipeName" // *must match this.state above
id="item"
placeholder="ex. Chicken Pot Pie"
onChange={this.onChange}
/>
<Label className={styles.inputLabel} for="item">
Ingredients
</Label>
<Input
type="textarea"
size="lg"
name="ingredients" // *must match this.state above
id={styles.ingredientsTextArea}
onChange={this.onChange}
/>
<Label className={styles.inputLabel} for="item">
Directions
</Label>
<Input
type="textarea"
size="lg"
name="directions" // *must match this.state above
id={styles.directionsTextArea}
onChange={this.onChange}
/>
<Button
color="dark"
style={{ marginTop: "2rem" }}
block
onClick={this.toggle}
>
Add
</Button>
</FormGroup>
</Form>
</ModalBody>
</Modal>
</div>
<div
id={styles.recipeListWrapper}
className="recipe-list-container"
>
{this.state.recipes.map(recipe => (
<RecipeItem
id={recipe._id}
title={recipe.title}
ingredients={recipe.ingredients}
directions={recipe.directions}
beingViewed={recipe.beingViewed}
viewRecipe={this.viewRecipe}
closeRecipe={this.closeRecipe}
deleteRecipe={this.deleteRecipe}
/>
))}
</div>
</div>
</div>
</div>
</div>
);
} else {
return (
<p className="text-center jumbotron mt-5">{this.state.errors.msg}</p>
);
}
}
}
这是我的服务器.js:
const express = require("express");
const path = require('path');
const cors = require("cors");
const bodyParser = require("body-parser");
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const port = process.env.PORT || 5000;
app.use(bodyParser.json());
app.use(cors());
app.use(
bodyParser.urlencoded({
extended: false
})
);
dotenv.config();
const db = process.env.DB_CONNECT;
const Users = require("./routes/Users");
const Recipes = require("./routes/Recipes");
app.use("/users", Users);
app.use("/recipes", Recipes);
mongoose
.connect(db, {
useUnifiedTopology: true,
useNewUrlParser: true,
useCreateIndex: true
})
.then(() => console.log("MongoDB Connected..."))
.catch(() => console.log(err));
app.post("/viewrecipe/:id", (req, res) => {
Recipe.findOneAndUpdate({ _id: req.params.id }, { $set: { beingViewed: true } })
.then(res.send("Recipe being viewed."))
.catch(err => console.log(err));
});
app.post("/closerecipe/:id", (req, res) => {
Recipe.findOneAndUpdate({ _id: req.params.id }, { $set: { beingViewed: false } })
.then(res.send("Recipe closed."))
.catch(err => console.log(err));
});
app.get("/showrecipes", (req, res) => {
Recipe.find({}).then(recipes => res.send(recipes));
});
app.delete("/deleterecipes", (req, res) => {
Recipe.deleteMany({}).then(res.send("All recipes deleted. Database empty."));
});
// Serve static assets if in production
if(process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
如有必要,这里是实际路由("recipes."是具有/recipes 基础的快速路由器(:
recipes.get("/:useremail", (req, res) => {
if (!req.params.useremail) {
res.send("You must be logged in to access recipes.");
}
Recipe.find({
user_email: req.params.useremail
})
.then(recipes => {
res.send(recipes)
.catch(err => {
res.send("error: " + err);
});
});
任何帮助不胜感激!
在您的获取请求中,尝试使用 192.168.17.161:5000 而不是 localhost:5000