You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MERN应用Fetch API删除数据遇404错误,求技术排查

MERN应用删除功能404错误排查与解决

开发MERN应用时,使用Fetch API实现删除数据功能,点击删除按钮后页面提示"cannot delete.",请求返回404 Not Found。以下是问题排查和解决方案:

核心问题分析

  • 后端缺少DELETE路由:后端未定义对应/demo/users/:userid的删除接口,这是404错误的直接原因。
  • 前端ID传递不匹配:删除按钮调用removeElm时传入obj._id(MongoDB自动生成ID),但前端过滤数据用的是item.userid,且后端无对应查询逻辑。
  • 前端状态更新逻辑错误:handleForm中设置form.userid时依赖异步更新的sid状态,导致存入数据库的userid为空或旧值。

修正后的后端代码

添加DELETE路由,根据自定义userid删除数据:

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');

// 连接MongoDB
main().catch(err => console.log(err));
async function main() {
  await mongoose.connect('mongodb://127.0.0.1:27017/demo');
  console.log('db connected');
}

// 定义Schema与Model
const userSchema = new mongoose.Schema({
  userid: Number,
  username: String,
  password: String
});
const UserModel= mongoose.model("User",userSchema);

const server = express();
// 中间件配置
server.use(cors());
server.use(bodyParser.json());

// 创建用户接口
server.post('/demo',async (req,res)=>{
  let user = new UserModel();
  user.userid  = req.body.userid;
  user.username = req.body.username;
  user.password = req.body.password;
  const savedDoc = await user.save();
  console.log(savedDoc);
  res.json(savedDoc);
})

// 查询所有用户接口
server.get('/demo',async (req,res)=>{
  const docs =  await UserModel.find({});
  console.log("All Docs=>"+docs);
  res.json(docs);
})

// 新增删除用户接口
server.delete('/demo/users/:userid', async (req, res) => {
  try {
    const userId = parseFloat(req.params.userid);
    const deletedUser = await UserModel.findOneAndDelete({ userid: userId });
    if (!deletedUser) {
      return res.status(404).send("User not found");
    }
    res.send("User deleted successfully");
  } catch (err) {
    res.status(500).send("cannot delete.");
  }
})

server.listen(9090,()=>{
  console.log(`Server is running on port 9090`);
})

修正后的前端代码

修复ID传递、状态更新等问题:

import { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [form, setForm] = useState({});
  const [users, setUsers] = useState([]);
  const [fname, setFName] = useState("");
  const [pass, setPass] = useState("");

  const handleName = (e) => {
    setFName(e.target.value);
  }

  const handlePass = (e) => {
    setPass(e.target.value);
  }

  const handleForm = (e) => {
    e.preventDefault();
    // 直接生成新ID并赋值,避免异步状态问题
    const newUserId = Math.random() + 1;
    setForm({
      userid: newUserId,
      username: fname,
      password: pass
    });
  }

  const removeElm = (userid) => {
    fetch(`http://localhost:9090/demo/users/${userid}`, {
      method: "DELETE",
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then(response => {
        if (!response.ok) throw new Error("cannot delete.");
        return response.text();
      })
      .then((message) => console.log(message))
      .then(() => {
        // 根据userid过滤列表
        setUsers(values => values.filter(item => item.userid !== userid))
      })
      .catch(err => console.log(err))
  }

  const handleSubmit = async (e) => {
    e.preventDefault();
    const response = await fetch("http://localhost:9090/demo", {
      method: 'POST',
      body: JSON.stringify(form),
      headers: {
        'Content-Type': 'application/json'
      }
    })

    const data = await response.json();
    console.log(form, response, data);
    // 提交后刷新用户列表
    getUsers();
  }

  const getUsers = async () => {
    const response = await fetch("http://localhost:9090/demo", {
      method: 'GET',
    })
    const data = await response.json();
    setUsers(data);
  }

  useEffect(() => {
    getUsers();
  }, [])

  return (
    <div className="App">
      <div>
        <form onSubmit={handleSubmit}>
          <label htmlFor="username">Username</label>
          <input type="text" name='username' onChange={handleName} />
          <label htmlFor="password">Password</label>
          <input type="text" name='password' onChange={handlePass} />
          <button onClick={handleForm}>Set User Data</button>
          <button type="submit">Submit</button>
        </form>
      </div>
      <ul>
        {users.map(obj => (
          <li key={obj.userid}>
            <span>Username:{obj.username}</span>, <span>Password:{obj.password}</span>
            {/* 传递正确的userid */}
            <button onClick={() => removeElm(obj.userid)}>Remove</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;

关键修正说明

  1. 后端:新增DELETE /demo/users/:userid接口,通过userid查找并删除用户,处理查询不到用户、服务器异常等情况。
  2. 前端:
    • 删除按钮传递obj.userid,与后端查询字段保持一致。
    • 修复handleForm的状态更新逻辑,直接生成ID并赋值给表单,避免异步状态延迟问题。
    • 优化删除请求的错误处理,捕获HTTP异常并提示。
    • 提交表单后调用getUsers()刷新列表,确保新增用户实时显示。

内容的提问来源于stack exchange,提问作者TUFMachine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 14:24:54