【发布时间】:2022-11-29 18:57:28
【问题描述】:
每次我在我的购买页面上时,一切正常并且更新正常。当我在页面中第一次点击提交时,它会正确更新我的数据库,但不会弹出警报窗口。 => 页面重新呈现并将自身设置为初始视图。如果我留在页面上并提交第二次购买,那么我会收到一个弹出框,提示无法通过 post 方法获取,然后弹出提示框,提示购买成功。即使发生故障,在功能上也没有任何错误。所有数据库文件都是最新的。有人请帮助我不知道我做错了什么。
我的前端 react.js
import React, { useState, useEffect } from 'react';
import { NumberFormat as numberFormat } from '../numberFormat';
export default function Purchase() {
// user input collection structure
const [form, setForm] = useState({
amount: '',
title: '',
})
// user spending limit
const [limit, setLimit] = useState({
balance: 0,
limit: 0,
})
useEffect(() => {
async function getLimit() {
const response = await fetch(`http://localhost:4000/balance/`);
if (!response.ok) {
const message = `An error occured at effect: ${response.statusText}`;
window.alert(message);
return;
}
const data = await response.json();
const userBal = data["balance"];
const userLim = 50 - parseFloat(userBal);
setLimit({ balance: userBal, limit: userLim });
}
getLimit();
return;
}, []);
// Update State Properties
function updateForm(value) {
return setForm((prev) => {
return { ...prev, ...value };
});
}
function validateInput(input){
input = input * 1000;
if (input%10 === 0) return false;
else return true;
}
async function onSubmit() {
// check that amount is valid
if (form.title === ''){
window.alert(`Please Include a Title for the payment`);
return;
}
const bal = parseFloat(limit.balance);
const lim = parseFloat(limit.limit);
const amt = parseFloat(form.amount);
if (amt > lim || amt === 0 || amt === '' || validateInput(amt)){
window.alert(`Invalid Amount ${form.amount}.\nPlease enter value greater than 0.00 within ${lim}.`);
return;
}
const newPurchase = {
type: 'purchase',
amount: form.amount,
title: form.title,
balanceToSet: amt + bal
}
await fetch(`http://localhost:4000/purchase/add`, {
method: 'POST',
mode:'cors',
headers: {
'Access-Control-Allow-Origin': '*',
"Content-Type": 'application/json; charset=UTF-8',
},
body: JSON.stringify(newPurchase)
}
)
.then((response) => response.json()).then((data)=> {console.log(data);
})
.catch((err) => {
window.alert(`post fetch error ${err.message}`);
return;
});
window.alert(`Purchase ${form.title} of amount $${form.amount} posted.`);
return;
}
return (
// Will Display
<div className='home'>
{/* Title */}
<h1 className='hometitle'>
Make A Purchase
</h1>
<div>
<h1> Your Fizz Balance: {numberFormat(limit.balance)}</h1>
<h1> Your Fizz Allowance: {numberFormat(limit.limit)}</h1>
</div>
{/* Current Allowance */}
{/* Debt owed to fizz */}
{/* Make Purchase Form
If incorrect parameters then show text saying invalid amount below
On submission alert shows telling user a purchase of certain amount was made
render rest of the page */}
<form onSubmit={onSubmit}>
<div className="form-group">
<label htmlFor='title'>Title:</label>
<input
type='text'
id='name'
value={form.title}
onChange={(e) => updateForm({ title: e.target.value })}
/>
</div>
<div className="form-group">
<label htmlFor="amount">Amount:</label>
<input
type="text"
id="amount"
value={form.amount}
onChange={(e) => updateForm({ amount: e.target.value })}
/>
</div>
<div>
<input
type='submit'
value='Make Purchase'
/>
</div>
</form>
</div>
);
}
我的后端 node.js
const express = require("express");
const purchaseRoutes = express.Router();
const dbo = require("../db/connection");
const { floor } = require('mathjs');
// Add purchase to History Table and update balance in user info
purchaseRoutes.route("/purchase/add").post(
async function (req, response) {
let db_connect = dbo.getDb();
// Writing Purchase to History Table
let thisPurchase = {
type: req.body.type,
amount: parseFloat(req.body.amount),
title: req.body.title,
rfndStatus: false,
date: Date.now()
};
let queryParams = { name: "user" };
// post query contents
let updatedBalance = {
$set: {
balance: floor(req.body.balanceToSet * 1000) / 1000
}
};
const session = db_connect.startSession();
const transactionDetails = {
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' }
}
try {
const transactionResults = await session.withTransaction(async () => {
const userColl = db_connect.db('fizzData').collection('userData');
const histColl = db_connect.db('fizzData').collection('transHist');
await userColl.updateOne(queryParams, updatedBalance,{session});
await histColl.insertOne(thisPurchase,{session});
}, transactionDetails);
response.json(transactionResults);
console.log(transactionResults);
} catch(e){
console.log(`transaction failed ${e}`)
}
finally {
await session.endSession();
}
});
在 postman 中,我使用相同的标头、url 和正文测试了我的 fetch 调用,我的回应是这样的。
{"ok":1,"$clusterTime":{"clusterTime":{"$timestamp":"7171344646893731861"},"signature":{"hash":"qwfNCLTeYc+/Gr79JghaSuDtZvQ=","keyId":{" low":8,"high":1659459863,"unsigned":false}}},"operationTime":{"$timestamp":"7171344646893731861"}}
我认为这可能是一个 cors 问题,所以我在 chrome 中安装了 cors 扩展并将模式标签添加到标题中。问题不在于 useEffect 中的提取或至少是调用,因为它正确地从数据库中调用了正确的值。
【问题讨论】:
-
您在第二次尝试保存时会收到哪些警报?您能否在代码中指出出现问题时正在执行的
window.alert块? -
@ShubhamWaje 它们按连续顺序弹出,两个窗口警报都接近 onSubmit 函数的末尾。此外,当我检查开发工具中的网络选项卡时,那些发布请求根本不会显示在第一个上。然后在第二个它尝试拨打电话并取消。
-
我也刚刚对提交进行了一些更改,发现现在根本没有弹出窗口出现,但也没有弹出错误。但是,请求根本没有记录在开发工具的网络选项卡中。我没有设置 .catch,而是设置了 fetch = response,然后如果响应正常,我调用弹出窗口向用户报告成功。
-
此外,这不会在开发人员工具的“我的网络”选项卡中记录任何后调用。我是一周大的 React 用户,所以我仍然熟悉该语言的语法和属性,但我有理由相信问题出在前端。我认为在获取完成之前购买页面正在渲染或重建。
标签: node.js reactjs mongodb fetch