Невозможно удалить по идентификатору из mongoDB в приложении nextjs

Я создаю приложение в NextJS для практики, и мне трудно получить отдельные данные для удаления из базы данных с помощью функции findByIdAndDelete.

CastError: приведение к ObjectId не удалось для значения «не определено» (строка типа) по пути «_id» для модели «Встреча»

./page.jsx:

import AddAppointment from "./addAppointment";
import DeleteAppointment from "./deleteAppointment";
import UpdateAppointment from "./updateAppointment";

async function getAppointment() {
  const res = await fetch("http://localhost:3000/api/appointment", {
    method: "GET",
    cache: "no-store",
  });
  // const data = await res.json();
  return res.json();
}

async function Appointment() {
  const { appointment } = await getAppointment();

  return (

    <div className = "py-10 px-10">
      <div className = "py-2">
        <AddAppointment />
      </div>
      <table className = "table w-full">
        <thead>
          <tr>
            <th>#</th>
            <th>Nama</th>
            <th>Tanggal</th>
            <th>No Telp.</th>
            <th>Terapis</th>
            <th>Status</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {appointment.map((row, i) => (
            <tr key = {row._id}>
              <td>{i + 1}</td>
              <td>{row.name}</td>
              <td>{row.date}</td>
              <td>{row.phone}</td>
              <td>{row.terapist}</td>
              <td>{row.statust || "unknown"}</td>
              <td className = "flex">
                <UpdateAppointment {...appointment} />
                <DeleteAppointment {...appointment} />
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export default Appointment;

./deleteAppointment.jsx:

"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";

export default function DeleteAppointment() {
  const [modal, setModal] = useState(false);

  const router = useRouter();

  async function handleDelete({ id }) {
    await fetch(`http://localhost:3000/api/appointment?id=${id}`, {
      method: "DELETE",
    });

    router.refresh();
    setModal(false);
  }

  function handleChangeEvent() {
    setModal(!modal);
  }

  return (
    <div>
      <button className = "btn btn-error btn-sm" onClick = {handleChangeEvent}>
        Delete
      </button>

      <input
        type = "checkbox"
        checked = {modal}
        onChange = {handleChangeEvent}
        className = "modal-toggle"
      />

      <div className = "modal">
        <div className = "modal-box">
          <h3 className = "font-bold text-lg">
            Anda yakin untuk menghapus data ""?
          </h3>

          <div className = "modal-action">
            <button type = "button" className = "btn" onClick = {handleChangeEvent}>
              Close
            </button>
            <button type = "button" onClick = {handleDelete} className = "btn">
              Delete
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

Маршрут API:

import { connectMongoDB } from "@/lib/mongodb";
import Appointment from "@/models/appointment";
import { NextResponse } from "next/server";

export async function DELETE(req) {

  const id = req.nextUrl.searchParams.get("id");
  await connectMongoDB();
  await Appointment.findByIdAndDelete(id);
  return NextResponse.json({ message: "Appointment deleted" }, { status: 200 });
}

Модель:

import mongoose, { Schema, models } from "mongoose";

const appointmentSchema = new Schema(
  {
    name: {
      type: String,
      required: true,
    },
    date: {
      type: String,
      required: true,
    },
    phone: {
      type: String,
      required: true,
    },
    terapist: {
      type: String,
      required: true,
    },
    statust: {
      type: String,
      required: true,
    },
  },
  { timestamps: true }
);

const Appointment =
  models.Appointment || mongoose.model("Appointment", appointmentSchema);
export default Appointment;

CastError: приведение к ObjectId не удалось для значения «не определено» (строка типа) по пути «_id» для модели «Встреча»

Трудно понять, как пройти id и разницу между id и _id.

С помощью функции onClick вы не отправляли идентификатор функции удаления. Итак, идентификатор — undefined, а undefined — это не ObjectId. Поэтому он не может найти соответствующие данные из базы данных. Вам нужно отправить соответствующую строку или только значение идентификатора в качестве реквизита: <DeleteAppointment row = {row} /> или <DeleteAppointment id = {row.id} /> затем получает реквизит в качестве параметра в компоненте DeleteAppointment. Затем используйте props.id или props.row.id в идентификаторе запроса вместо параметра id, например: await fetch(http://localhost:3000/api/appointment?id=${props.id}} или, если вы отправили строку, используйте props.row.id

Onur Doğan 06.04.2024 15:28

вау, это работа, спасибо, это действительно помогло мне лучше понять, как передавать реквизиты дочернему компоненту

eko pram 06.04.2024 17:34
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
2
160
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Кажется, что ошибка произошла не в вашей базе данных, а в том месте, где вы передаете идентификатор. Можете ли вы проверить, какое значение в id ошибка указывает, что id, который вы передаете, не определен. Пожалуйста, проверьте значение и убедитесь, что оно передается правильно.

Ответ принят как подходящий

С помощью функции onClick параметр не передается. Итак, параметр id — это undefined. Поэтому он отправляет запрос API с параметром undefined id следующим образом: http://localhost:3000/api/appointment?id=undefined

На стороне клиента необходимо использовать ObjectID для удаления документа с помощью findByIdAndDelete(), но параметр ID поступает из запроса как undefined, а не как ObjectID. Поэтому он не может найти связанный документ в БД и возвращает эту ошибку.

В результате проблема связана с клиентской стороной. Необходимо отправить правильный идентификатор для удаления с помощью параметра API. Поэтому необходимо получить связанную строку или только значение id в качестве реквизита в компоненте DeleteAppointment.

Было бы лучше отправить весь объект строки в реквизит, если вам нужно будет использовать и другие поля:

// Send related row as prop 
<DeleteAppointment row = {row} />

В противном случае достаточно отправить только id:

// Send only the related row's ID field as a prop
<DeleteAppointment id = {row.id} />

Затем получите реквизит в качестве параметра в компоненте DeleteAppointment:

export default function DeleteAppointment(props) {
...
}

После этого, из-за достижения связанного идентификатора в реквизите, вы можете использовать props.id или props.row.id в идентификаторе запроса вместо параметра id:

async function handleDelete() {
  await fetch(`http://localhost:3000/api/appointment?id=${props.id}`, {
      method: "DELETE",
  });

  router.refresh();
  setModal(false);
}

Если вы отправите весь объект строки в качестве реквизита, вы можете использовать props.row.id:

async function handleDelete() {
  await fetch(`http://localhost:3000/api/appointment?id=${props.row.id}`, {
      method: "DELETE",
  });

  router.refresh();
  setModal(false);
}

Надеюсь, понятно и полезно

Другие вопросы по теме