尝试在 React 前端渲染 MongoDB 条目 10 秒后超时
Posted
技术标签:
【中文标题】尝试在 React 前端渲染 MongoDB 条目 10 秒后超时【英文标题】:Attempt to render MongoDB entries in React front-end times out after 10 seconds 【发布时间】:2021-01-26 12:14:33 【问题描述】:我想渲染一张“卡片”,其中包含从 MongoDB 数据库中提取的某些细节,并作为道具传递给 React 前端。后端是一个无服务器功能。
目前,我无法让我的 React 代码找到我的 MongoDB 条目。它不断超时并显示以下错误消息:
2020-10-12T15:25:11.119Z cde99f57-0da2-4b71-9fc1-d2eda3c1369c ERROR (node:8) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option useUnifiedTopology: true to the MongoClient constructor.
2020-10-12T15:25:21.062Z cde99f57-0da2-4b71-9fc1-d2eda3c1369c Task timed out after 10.01 seconds
每次重新加载页面后都会发生这种情况 - 请求一直超时。
谁能指出我在这里做错了什么?
这是我的代码...
架构:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const SubmitDebtSchema = new Schema (
creditCard: String,
personalLoan: String,
provider: String,
balance: Number,
limit: Number,
monthly: Number,
interest: Number,
borrowed: Number
);
module.exports = mongoose.model('submitdebts', SubmitDebtSchema);
我的“获取”API 函数:
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const SubmitDebt = require("./submitDebtSchema");
require("dotenv").config();
const app = express();
app.use(bodyParser.urlencoded(
extended: true
));
mongoose.connect(`mongodb+srv://$process.env.MONGO_USER:$process.env.MONGO_PASSWORD@otter-money.f9twk.mongodb.net/test?retryWrites=true&w=majority`, useNewUrlParser: true, useUnifiedTopology: true);
module.exports = async (req, res) =>
res.statusCode = 200;
res.setHeader("Content-Type", "application/json");
await SubmitDebt.find();
;
我的反应代码:
class IndividualDebts extends Component
constructor(props)
super(props)
this.state =
debts:
this.getDebtCards = this.getDebtCards.bind(this);
this.renderDebtCards = this.renderDebtCards.bind(this);
componentDidMount = () =>
this.getDebtCards()
getDebtCards = () =>
axios.get("/api/fetchDebtCards")
.then((res) =>
const data = res.data
this.setState (
debts: data
)
console.log("Data has been received.")
)
.catch((error) =>
alert("Error fetching the data.")
console.log(error)
)
renderDebtCards = (debts) =>
if (!this.state.debts.length)
return null
this.state.debts.map((debt, index) =>
return (
<div>
<IndividualDebtCard key=index
provider=debt.provider
type=debt.creditCard === 'true' ? debt.creditCard : "Personal Loan"
balance=debt.balance
limit=debt.creditCard === 'true' ? debt.limit : debt.borrowed
monthly=debt.monthly
interest=debt.interest />
</div>
)
)
render()
return (
<div>
<section className="individual-debts-section">
<div className="individual-debts-container">
<div className="individual-debts-heading">
<h3>Individual Breakdown</h3>
</div>
<div className="individual-debts-card-container">
this.renderDebtCards()
</div>
我觉得它真的很接近,但我就是不知道我做错了什么!有什么建议吗?
谢谢
【问题讨论】:
对象的方法是什么? mongoose 文档只说明 find。 尝试添加“.default”,现在“SubmitDebt”在错误日志中是匿名的。我指的文档也是这样的:mongoosejs.com/docs/api.html#model_Model.find 嘿 - 再次感谢您的回复。真的很感激。我真的不明白我需要如何根据您的最新回复重构我的代码。您能否为我添加一个答案以便我查看? 请查看:***.com/questions/34241970/… 感谢您的反馈。我现在已经转换了我的代码以反映答案。它仍然无法正常工作,但会更新我的问题以反映新的错误消息。 【参考方案1】:您的 API 设置存在一些问题...
解决方案的问题
调整您的 submitdebts
模型以返回当前注册的模型或使用 mongoose 连接注册架构:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
...Schema
module.exports = mongoose.models.submitdebts || mongoose.model('submitdebts', SubmitDebtSchema);
如果您的前端和后端在不同的进程上运行,则需要添加 CORS 标头(我喜欢将 package 用于 CORS):
/*
Either add CLIENT to your .env files:
CLIENT: http://example.com (for production)
CLIENT: http://localhost:3000 (for development)
...etc
or add it to your your startup script in the package.json:
for example: "dev": "NODE_ENV=development CLIENT=http://localhost:3000 node server.js"
This is important to allow requests from the client
*/
...required imports
const cors = require("cors");
const CLIENT, ...etc = process.env;
...startup script
app.use(
cors(
origin: CLIENT
)
);
...listen to port
mongoose.connect
是异步的,因此您当前在连接和启动服务器时会遇到竞速情况。相反,您应该等待连接解决,然后启动您的快速服务器。此外,您检索文档的控制器没有正确响应客户端的请求:
const CLIENT, MONGO_USER, MONGO_PASSWORD, PORT = process.env;
const options =
useNewUrlParser: true, // avoids DeprecationWarning: current URL string parser is deprecated
useCreateIndex: true, // avoids DeprecationWarning: collection.ensureIndex is deprecated.
useFindAndModify: false, // avoids DeprecationWarning: collection.findAndModify is deprecated.
useUnifiedTopology: true // avoids DeprecationWarning: current Server Discovery and Monitoring engine is deprecated
;
(async () =>
try
// if this fails to connect after 10 seconds, it'll kill the process
// so make sure your credentials and host URL are correct!!!!!
await mongoose.connect(`mongodb+srv://$MONGO_USER:$MONGO_PASSWORD@otter-money.f9twk.mongodb.net/test?retryWrites=true&w=majority`, options);
const app = express();
app.use(bodyParser.urlencoded( extended: true ));
// this now tells express to accept requests from the client
app.use(
cors(
origin: CLIENT
)
);
// this will accept any GET requests to "/api/fetchDebtCards"
// and respond with "debts" (can be named anything)
app.get("/api/fetchDebtCards", async (req, res) =>
try
const debts = await SubmitDebt.find();
res.status(200).json( debts );
/*
Optionally, you can use:
res.status(200).send(debts)
which will allow "debts" to be directly accessible from "res.data"
*/
catch (error)
res.status(400).json( error );
);
app.listen(PORT, (err) =>
if (err) throw err;
console.log(`Listening for requests from: \x1b[1m$CLIENT\x1b[0m\n`);
);
catch (err)
console.log(err.toString());
process.exit(1);
)();
现在在客户端上,您应该能够从 res.data.debts
检索“债务”文档(我更喜欢 async/await
而不是 thenables,但取决于您):
getDebtCards = async () =>
try
const res = await axios.get("/api/fetchDebtCards");
console.log("Data has been received: ", JSON.stringify(res.data.debts, null, 4))
this.setState( debts: res.data.debts );
catch(error)
alert("Error fetching the data.")
console.log(error)
代码
server.js
require("dotenv").config();
const bodyParser = require("body-parser");
const cors = require("cors");
const express = require("express");
const mongoose = require("mongoose");
const SubmitDebt = require("./submitDebtSchema");
const CLIENT, MONGO_USER, MONGO_PASSWORD, PORT = process.env;
const options =
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true
;
(async () =>
try
await mongoose.connect(`mongodb+srv://$MONGO_USER:$MONGO_PASSWORD@otter-money.f9twk.mongodb.net/test?retryWrites=true&w=majority`, options);
const app = express();
app.use(bodyParser.urlencoded( extended: true ));
app.use(
cors(
origin: CLIENT
)
);
app.get("/api/fetchDebtCards", async (req, res) =>
try
const debts = await SubmitDebt.find();
res.status(200).json( debts );
catch (error)
res.status(400).json( error );
);
app.listen(PORT, (err) =>
if (err) throw err;
console.log(`Listening for requests from: \x1b[1m$CLIENT\x1b[0m\n`);
);
catch (err)
console.log(err.toString());
process.exit(1);
)();
结论
您应该能够只启动 express 服务器并使用Postman 对其进行查询。例如,我在http://localhost:5000
运行一个开发快递服务器,我将使用GET http://localhost:5000/api/users
进行查询,我将返回users
的JSON 响应:
【讨论】:
感谢详细的回复。这段代码不可避免地会比我的更彻底和更有效,但最后我发现我的 Axios 查询有问题,而且我没有在我的 Fetch API 文件中返回正确的 JSON。我会接受但没有使用它 - 感谢您的宝贵时间!【参考方案2】:在 JSX 中调用 this.rennderDebtCards 方法时,您没有提供任何参数。要么传递 this.state.debts,要么直接在你的方法中使用 this.state.debts
renderDebtCards = () =>
if (this.state.debts.length === 0)
return null
return this.state.debts.map((debt, index) =>
return (
<div>
<IndividualDebtCard key=index
provider=debt.provider
type=debt.creditCard === 'true' ? debt.creditCard : "Personal Loan"
balance=debt.balance
limit=debt.creditCard === 'true' ? debt.limit : debt.borrowed
monthly=debt.monthly
interest=debt.interest />
</div>
)
)
【讨论】:
嘿 - 我试过这个,但不幸的是它没有用。我在函数日志中收到一条单独的错误消息,提示“SubmitDebt.find() 不是函数”。 我认为这意味着您正在尝试对不允许执行的事情执行 mongo 查询。检查您的 SubmitDebt 是否正确导入并且是您的 mongo 模型 嘿 - 我已经做到了。我认为没关系,但为了安全起见,我已经添加了所有代码。如果您对更新后的问题有任何反馈,我们将不胜感激!以上是关于尝试在 React 前端渲染 MongoDB 条目 10 秒后超时的主要内容,如果未能解决你的问题,请参考以下文章
使用 node.js + react 服务器端渲染 + 通量 + mongodb 时的数据耦合策略