MERN栈银行应用MongoDB用户余额更新失败问题求助
问题分析与解决方案
你的核心问题是在React前端代码中直接连接并操作MongoDB,这完全违背了MERN架构的分层原则——前端只能通过调用后端API来间接操作数据库,不能直接连接数据库。另外你的后端也没有提供处理存款的API接口,前端自然无法完成余额更新。
修复步骤
1. 后端添加存款API路由
在router.js中扩展现有路由,添加处理存款的逻辑:
const express = require('express') const router = express.Router() const schemas = require('../models/schemas') router.post('/users/:a', async(req, res) => { const {name, email, password, balance, amount} = req.body const action = req.params.a switch(action) { case "send": const userData = {name: name, email: email, password: password, balance: balance} const newUser = new schemas.Users(userData) const saveUser = await newUser.save() if (saveUser) { res.send('User created') } else { res.send('Failed to create user. Please make sure all fields are filled and try again.') } break; // 新增存款处理逻辑 case "deposit": try { // 找到用户并累加余额(注意转换amount为数字) const updatedUser = await schemas.Users.findOneAndUpdate( { email: email }, { $inc: { balance: Number(amount) } }, // $inc用于累加,而非直接替换 { new: true } ) if (updatedUser) { res.send(`存款成功,当前余额:${updatedUser.balance}`) } else { res.send('未找到该用户') } } catch (err) { res.send('存款失败:' + err.message) } break; default: res.send('Invalid Request') break } }) module.exports = router
2. 重构前端DepositPage代码
去掉前端的mongoose连接,改用axios调用后端API,和创建账户的逻辑保持一致:
import { useEffect, useState } from "react" import { useNavigate, useLocation } from 'react-router-dom' import React from "react"; import Card from "../../partials/Card"; import axios from "axios"; // 引入axios function DepositPage() { const navigate = useNavigate(); const location = useLocation(); const [show, setShow] = useState(true); const [status, setStatus] = useState(''); return ( <Card bgcolor="dark" header="Deposit" status={status} body={show ? <DepositForm setShow={setShow} setStatus={setStatus}/> : <DepositMsg setShow={setShow}/>} /> ) } function DepositMsg(props){ return (<> <h5>User Successfully Deposited into Their Account</h5> <button type="submit" className="btn btn-light" onClick={() => props.setShow(true)}> Make Another Deposit </button> </>); } function DepositForm(props){ const [email, setEmail] = useState(''); const [amount, setAmount] = useState(''); const handleDeposit = async () => { try { const response = await axios.post('http://localhost:4000/users/deposit', { email: email, amount: amount }) props.setStatus(response.data); props.setShow(false); } catch (err) { props.setStatus('存款失败:' + err.response.data); } } return (<> Email<br/> <input type="input" className="form-control" placeholder="Enter email" value={email} onChange={e => setEmail(e.currentTarget.value)}/><br/> Amount<br/> <input type="number" className="form-control" placeholder="Enter amount" value={amount} onChange={e => setAmount(e.currentTarget.value)}/><br/> <button type="button" className="btn btn-light" onClick={handleDeposit}> Deposit </button> </>); } export default DepositPage
关键说明
- 前端永远不要直接连接数据库,所有数据库操作必须通过后端API完成,这是安全和架构规范的基本要求。
- 使用
$inc而非$set来更新余额,因为存款是累加金额,不是直接替换现有余额。 - 确保在API调用的异步逻辑完成后再更新前端状态(比如
setShow(false)),避免请求未完成就显示成功提示。
内容的提问来源于stack exchange,提问作者Michael McKinnon
相关产品推荐
相关产品推荐

