我正在try 创建一个发出删除请求的API,该请求将从数据库(MongoDB Atlas)中的用户文档中删除专辑.

我一直收到一个错误,说albumName属性是未定义的,我不知道为什么.

作为参考,用户将 Select 他们想要在页面上删除的专辑,它将删除该专辑.在数据库中,相册是一个由Always对象组成的数组,相册有两个属性,alumName和Asfits(另一个数组).

该接口删除:

import { connect } from "@/dbConfig/dbConfig";
import User from "@/models/userModel";
import { NextRequest, NextResponse } from "next/server";
import jwt from "jsonwebtoken";

connect();

export async function DELETE(request) {
  const token = request.cookies.get("token")?.value || '';
  const decodedToken = jwt.decode(token);
  const email = decodedToken ? decodedToken.email : '';
  
  const albumName = request.query.albumName; // Extract albumName from query params

  try {
    const userEmail = email.toLowerCase();

    if (!userEmail || !albumName) {
      return NextResponse.json({ error: "Email or albumName not provided" }, { status: 400 });
    }

    const user = await User.findOneAndUpdate(
      { email: userEmail },
      { $pull: { albums: { albumName: albumName } } },
      { new: true }
    );

    if (!user) {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }

    if (!user.albums.find(album => album.albumName === albumName)) {
      return NextResponse.json({ error: "Album not found in user's albums" }, { status: 404 });
    }

    return NextResponse.json({ success: true, message: "Album deleted successfully" });
  } catch (error) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}

专辑页面.js:

'use client';

import { useEffect, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTrashCan } from '@fortawesome/free-solid-svg-icons'
import Link from 'next/link';
import axios from 'axios';

export default function AlbumsPage() {
  const [albumName, setAlbumName] = useState('');
  const [albums, setAlbums] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const [deleteAlbumName, setDeleteAlbum] = useState(''); 
  const [errorMessage, setErrorMessage] = useState('');

  const fetchAlbums = async () => {
    try {
      const response = await axios.get('/api/users/getUserAlbums');
      setAlbums(response.data.albums);
    } catch (error) {
      console.log(error);
    }
  };

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

  const handleCreateAlbum = () => {
    setShowModal(true);
    setErrorMessage('');
  };

  const handleModalInputChange = (e) => {
    setAlbumName(e.target.value);
    setErrorMessage('');
  };

  const handleModalClose = () => {
    setShowModal(false);
    setAlbumName('');
  };

  const handleModalSubmit = async () => {
    try {
      const response = await axios.post('/api/users/createAlbums', { albumName });
      console.log(albumName);

      setAlbums(prevAlbums => [...prevAlbums, { albumName }]);
      setShowModal(false);
      setAlbumName('');
    } catch (error) {
      if (error.response) {
        if (error.response.status === 400) {
          setErrorMessage('Album already exists');
        } else {
          setErrorMessage('Failed to create album');
        }
      } else {
        setErrorMessage('Network error. Please try again.');
      }
    }
  };

  const handleDeleteAlbum = async (albumName) => {
    setDeleteAlbum(albumName); 
    setShowModal(true); 
  };

  const confirmDeleteAlbum = async () => {
    if (deleteAlbumName) { 
      console.log('Deleting album:', deleteAlbumName); // Log the album name
      try {
        const response = await axios.delete(`api/users/deleteAlbums?albumName=${deleteAlbumName}`);
        setShowModal(false);
        setDeleteAlbum('');
        fetchAlbums(); 
      } catch (error) {
        console.log(error);
        console.log('Failed to delete album');
      }
    }
  };
  
  

  useEffect(() => {
    const handleKeyPress = (event) => {
      if (event.key === 'Enter') {
        event.preventDefault();
        handleModalSubmit();
      }
    };
    document.addEventListener('keydown', handleKeyPress);
    return () => {
      document.removeEventListener('keydown', handleKeyPress);
    };
  }, [albumName]);

  return (
    <main>
      {showModal && (
        <div className="fixed top-0 left-0 w-full h-full flex items-center justify-center bg-gray-500 bg-opacity-50 z-50"></div>
      )}
  
      {showModal && (
        <div className="fixed top-0 left-0 w-full h-full flex items-center justify-center z-50">
          <div className="bg-white p-10 rounded-md shadow-lg">
            {deleteAlbumName ? ( 
              <>
                <h2 className="text-lg font-semibold mb-2">Are you sure you want to delete this album?</h2>
                <div className="flex items-center justify-center">
                  <button className="bg-black text-white px-4 py-2 rounded-md mr-2 font-semibold" onClick={confirmDeleteAlbum}>Yes</button>
                  <button className="bg-gray-300 text-gray-800 px-4 py-2 rounded-md font-semibold" onClick={handleModalClose}>No</button>
                </div>
              </>
            ) : (
              <>
                <h2 className="text-lg font-semibold mb-2">Enter Album Name</h2>
                {errorMessage && <p className='text-sm text-red-500 mb-2'>{errorMessage}</p>}
                <input
                  type="text"
                  className="border border-gray-300 rounded-md p-2 mb-2 outline-none"
                  value={albumName}
                  onChange={handleModalInputChange}
                  placeholder='Album Name'
                />
                <div className="flex items-center justify-center">
                  <button className="bg-black text-white px-4 py-2 rounded-md mr-2 font-semibold" onClick={handleModalSubmit}>Create</button>
                  <button className="bg-gray-300 text-gray-800 px-4 py-2 rounded-md font-semibold" onClick={handleModalClose}>Cancel</button>
                </div>
              </>
            )}
          </div>
        </div>
      )}
  
      <div className="flex flex-col items-center justify-center bg-gray-300 shadow-lg p-4">
        <h1 className="font-bold text-3xl mb-4">Albums</h1>
        <button className="bg-black text-white px-4 py-2 rounded-xl mb-4 font-semibold" onClick={handleCreateAlbum}>
          Create Album
        </button>
      </div>
  
      <div className="grid grid-cols-3 gap-4 m-5">
        {albums.map((album, index) => (
          album && album.albumName && ( 
            <div key={index} className="bg-white rounded-lg shadow-md p-4 relative text-center">
              <Link href={`/albums/${album.albumName}`} className="text-lg font-semibold mb-2 hover:opacity-70">{album.albumName}</Link>
              <button
                className="absolute bottom-0 right-0 bg-transparent text-white px-4 py-2 rounded-md font-semibold"
                onClick={() => handleDeleteAlbum(album.albumName)}
                title='Delete Album'
              >
                <FontAwesomeIcon icon={faTrashCan} className='text-red-500' />
              </button>
            </div>
          )
        ))}
      </div>
    </main>
  );
}

推荐答案

您try 获取查询参数的方式在app路由中是不正确的.正如你在doc上看到的,它应该是这样的:

export function DELETE(request) {
  // ...

  const searchParams = request.nextUrl.searchParams
  const albumName = searchParams.get('albumName')

  //...
}

此外,您可能希望在confirmDeleteAlbum中的客户端上使用绝对URL,并等待fetchAlbums以更好地同步更改:

const confirmDeleteAlbum = async () => {
  if (deleteAlbumName) {
    console.log("Deleting album:", deleteAlbumName); // Log the album name
    try {
      const response = await axios.delete(`/api/users/deleteAlbums?albumName=${deleteAlbumName}`);
      setShowModal(false);
      setDeleteAlbum("");
      await fetchAlbums();
    } catch (error) {
      console.log(error);
      console.log("Failed to delete album");
    }
  }
};

Javascript相关问答推荐

如何解决chrome—extension代码中的错误,它会实时覆盖google—meet的面部图像?'

Phaser 3 console. log()特定游戏角色的瓷砖属性

切换时排序对象数组,切换不起作用

Mongoose post hook在使用await保存时不返回Postman响应

当试图显示小部件时,使用者会出现JavaScript错误.

加载背景图像时同步旋转不显示的问题

Next.js服务器端组件请求,如何发送我的cookie token?

WhatsApp Cloud API上载问题:由于MIME类型不正确而导致接收&Quot;INVALID_REQUEST";错误

为什么客户端没有收到来自服务器的响应消息?

为什么JPG图像不能在VITE中导入以进行react ?

邮箱密码重置链接不适用于已部署的React应用程序

搜索功能不是在分页的每一页上进行搜索

在JS中动态创建对象,并将其追加到HTML表中

无法读取未定义的属性(正在读取合并)-react RTK

Docent.cloneNode(TRUE)不克隆用户输入

使用Reaction窗体挂钩注册日历组件

Reaction即使在重新呈现后也会在方法内部保留局部值

为什么我看到的是回复,而不是我的文档?

如何在Java脚本中并行运行for或任意循环的每次迭代

单击子按钮时将活动切换类添加到父分区