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

Next.js+React调用API删除MongoDB文档不生效问题

MongoDB单条文档删除功能失效修复

问题说明

核心需求为从MongoDB集合删除单条文档,现有实现逻辑为:index页面遍历渲染数据库查询返回的条目列表,将每个条目对象传入DeleteTest删除组件;组件内放置删除按钮,点击触发deleteTestFun函数调用后端删除API,运行时API始终无法正常完成删除操作。

现有代码

index页面代码

import React, { useState } from 'react';
import AppBar from '@mui/material/AppBar';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
import CardMedia from '@mui/material/CardMedia';
import CssBaseline from '@mui/material/CssBaseline';
import Grid from '@mui/material/Grid';
import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import Form from '../components/form';
import DeleteIcon from '@mui/icons-material/Delete';
import connectMongo from '../utlis/connectMongo';
import Test from '../models/testModel';
import Checkbox from '@mui/material/Checkbox';
import DeleteTest from '../components/deleteTest';
const theme = createTheme();

export default function Album({ tests }) {
  return (
    <div>
      <Form></Form>
      <div>
        {tests.map((test) => (
          <a key={test._id}>
            <p>
              {test.name} {test.email}
            </p>
            <DeleteTest test={test}></DeleteTest>
          </a>
        ))}
      </div>
    </div>
  );
}

export const getServerSideProps = async () => {
  try {
    console.log('CONNECTING TO MONGO');

    await connectMongo();

    console.log('CONNECTED TO MONGO');
    console.log('FETCHING DOCUMENTS');

    const tests = await Test.find();

    console.log('FETCHED DOCUMENTS');

    return {
      props: {
        tests: JSON.parse(JSON.stringify(tests)),
      },
    };
  } catch (error) {
    console.log(error);
    return {
      notFound: true,
    };
  }
};

DeleteTest删除组件代码

import React, { useState } from 'react';
import Button from '@mui/material/Button';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
import CardMedia from '@mui/material/CardMedia';
import CssBaseline from '@mui/material/CssBaseline';
import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import DeleteIcon from '@mui/icons-material/Delete';

export default function DeleteTest(props) {
  const postID = props.test._id;
  const name = props.test.name;
  const deleteTestFun = async (postID) => {
    const response = await fetch('/api/delete/' + postID, {
      method: 'DELETE',
    });
    const data = await response.json();
    console.log(data);
  };

  return (
    <div>
      <Button onClick={deleteTestFun}>Delete</Button>
    </div>
  );
}

API路由初始版本代码

import connectMongo from '../../../utlis/connectMongo';
import Test from '../../../models/testModel';
import { MongoClient } from 'mongodb';
import mongoose from 'mongoose';
/**
 *
 * @param {import("next").NextApiRequest} req
 * @param {import("next").NextApiResponse} res
 */

export default async function deleteTest(req, res) {
  try {
    const object = Test.find({ _id: req.query.postID });
    console.log(object.name);
    await Test.findOneAndDelete({ name: req.query.name });
    res.send('Item deleted');
  } catch (error) {
    console.log(error);
  }
}

API路由更新版本代码

export default async function deleteTest(req, res) {
    try{
      console.log(req.body.name);
      const test = await Test.remove(req.body)
      
    res.send('Item deleted');
    }catch(error)
    {
      console.log(error)
    }
  }

问题根因

  • 前端参数传递错误:deleteTestFun绑定按钮点击事件时,默认接收的参数是点击事件对象,而非组件内定义的postID变量,导致请求路径拼接的ID实际是事件对象,后端无法获取正确的文档ID;初始版本API尝试读取req.query.name,但前端请求未传递name字段,查询条件完全不匹配。
  • 后端缺少数据库连接步骤:两个版本的API都未执行connectMongo初始化数据库连接,直接调用Model方法无法执行数据库操作。
  • 数据库操作逻辑错误:初始版本中Test.find()返回的是Mongoose Query对象,未加await获取查询结果就直接读取object.name会直接报错;使用name字段作为删除条件,存在重名时会误删数据,必须使用文档唯一标识_id作为删除条件。
  • Mongoose方法使用错误:更新版本使用的Test.remove()方法已在新版Mongoose中废弃,且未传入正确的匹配条件,也未将前端传来的字符串ID转换为MongoDB可识别的ObjectId格式,无法匹配到对应文档。

修复方案

1. 修复DeleteTest组件

移除deleteTestFun的形参,直接使用闭包内提前获取的postID发起请求,删除成功后可刷新页面拉取最新列表:

export default function DeleteTest({ test }) {
  const postID = test._id;
  const deleteTestFun = async () => {
    const response = await fetch(`/api/delete/${postID}`, {
      method: 'DELETE',
    });
    const data = await response.json();
    console.log(data);
    // 删除成功后刷新列表,可替换为状态更新实现无刷新效果
    window.location.reload();
  };

  return (
    <div>
      <Button onClick={deleteTestFun} startIcon={<DeleteIcon />}>Delete</Button>
    </div>
  );
}

2. 修复删除API路由

首先初始化数据库连接,从路径参数获取文档ID并转换为ObjectId格式,使用findByIdAndDelete方法按唯一ID删除,补充状态码返回和错误处理:

import connectMongo from '../../../utlis/connectMongo';
import Test from '../../../models/testModel';
import mongoose from 'mongoose';
/**
 *
 * @param {import("next").NextApiRequest} req
 * @param {import("next").NextApiResponse} res
 */

export default async function deleteTest(req, res) {
  try {
    // 初始化数据库连接
    await connectMongo();
    // 转换ID格式
    const postId = new mongoose.Types.ObjectId(req.query.postID);
    // 按ID删除文档
    const deleteResult = await Test.findByIdAndDelete(postId);
    
    if (!deleteResult) {
      return res.status(404).json({ msg: '待删除文档不存在' });
    }
    res.status(200).json({ msg: '删除成功', data: deleteResult });
  } catch (error) {
    console.log(error);
    res.status(500).json({ msg: '删除失败', error: error.message });
  }
}

配置注意事项

  • 确认API路由文件命名符合Next.js动态路由规则,文件需命名为[postID].js,存放在pages/api/delete/目录下,才能正确匹配/api/delete/xxx格式的请求,拿到req.query.postID参数。
  • 若需要实现无刷新列表更新,可将条目列表的状态提升到index父组件,删除成功后通过回调函数过滤掉已删除的条目,无需整页刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:30:39