The query parameter is not defined in the router of my Next.js app API

I'm currently working on building an API endpoint for making DELETE requests to remove albums from a user's document in the MongoDB Atlas database.

Struggling with an error that keeps popping up, indicating that the albumName property is undefined and I can't seem to pinpoint the cause of it.

To provide some context, users will have the option to select which album they want to delete on a specific page, triggering the deletion process. In the database, albums are stored as an array of objects, each containing two properties: albumName and outfits (another array).

Delete API:

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 });
  }
}

Albums page.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>
  );
}

Answer №1

Attempting to retrieve the query parameter in the app router is not being done correctly. According to the documentation, it should be implemented like this:

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

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

  //...
}

Furthermore, it is advised to utilize an absolute URL on the client side within confirmDeleteAlbum and await the completion of fetchAlbums for better synchronization of changes:

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");
    }
  }
};

Answer №2

An issue has been identified with the delete request related to the albumName query parameter. The API attempts to access albumName from the query object, which results in an error indicating that the "albumName" property is undefined.

To resolve this error, adjust the following line in the Delete API:

  const albumName = request.params.albumName; // Retrieve albumName from params

Located in Page.js:

const response = await axios.delete(`api/users/deleteAlbums`, {
  params: {
    albumName: deleteAlbumName
  }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Embed" three.js within SmartMS

Is it possible to incorporate this simple three.js example into Smart Mobile Studio without extensive wrapping? I attempted to copy the window.onload content into an asm section but was unsuccessful. <!DOCTYPE html> <html> <head> <t ...

What is the best way to set up an anchor element to execute a JavaScript function when clicked on the left, but open a new page when clicked in

One feature I've come across on certain websites, like the Jira site, is quite interesting. For instance, if we take a look at the timeline page with the following URL - When you click on the name of an issue (which is an anchor element), it triggers ...

Ways to include extra information in a request when uploading images using Django's CKEditor?

On my website, I am utilizing django-ckeditor to allow users to input rich text content. Each webpage on the site represents a unique document identified by an id. For instance, two different documents will have separate webpages with URLs like - exampl ...

Can you tell me what this code on Facebook is for?

Upon inspection of Facebook's activity in my browser, I stumbled upon the following code snippet: for (;;);{"t":"refresh"} Attempting to decipher its purpose reveals an infinite loop. Can you identify its function? ...

Loop through a list of items and apply the bootstrap-select plugin to each

In an attempt to incorporate an update button within a loop using bootstrap-selectpicker, I encountered a challenge. Within each iteration of the loop, there is a form containing multiple select elements with selectpicker and a hidden button to save the se ...

The submission of an Angular form results in errors such as being unavailable or

After building a registration page component in Angular and following tutorials, I encountered a frustrating bug. When pressing the submit button on the form, the console would display "undefined" when attempting to access the NgForm's value. However, ...

Using React's higher order component (HOC) in TypeScript may trigger warnings when transitioning from non-TypeScript environments

I have a simple HOC component implemented in React with TypeScript. export const withFirebase = <P extends object>( Component: React.ComponentType<P> ) => class WithFirebase extends React.Component<P> { render() { return ...

Adjust Sidebar Height to Match Document Height (using React Pro Sidebar)

Having an issue with the height of a sidebar component in Next.js using React Pro Sidebar. It seems to be a JavaScript, HTML, and CSS related problem. I've tried several suggested solutions from Stack Overflow, but none of them seem to work. Surprisin ...

Utilizing JavaScript in AJAX Responses

Can I include JavaScript in an AJAX response and run it, or should I only use JSON or plain HTML for a more elegant solution? I'm trying to figure out the best way to handle AJAX requests that involve inserting HTML or running JavaScript based on user ...

Receiving a `forwardRef` issue while dynamically importing a module in Next.js

Has anyone encountered an issue with using forwardRef on an external component where ref.current does not reference the actual ref? I'm not sure if I'm missing something. This is what I'm trying to do: const Editor = dynamic(() => import ...

The AngularJS change event is not being activated

I am a beginner with angular js and I have implemented a bootstrap calendar in my application. However, I am facing an issue where the change event is not being triggered when the month changes, no matter where I place it within the code. Here is the snip ...

Showing attributes of models using Sequelize and Handlebars

As a novice in the world of programming, I am currently immersed in a website project where users can write and post articles. One crucial aspect I am focusing on is displaying the history of articles written by each user on their account page. Despite uti ...

What is the best way to implement a unique function in an angularjs directive?

Is it possible to execute a custom function when clicking on the checkbox of a table row shown below? I am using the Angular Smart Table directive and need to be able to store the rowid or another property of the rows when the checkbox is clicked. app.dir ...

Reloading the ASP.NET MVC bootstrap modal using Ajax for a fresh look

I'm struggling with my bootstrap modal. Whenever I click the submit button, the page refreshes and the modal disappears. How can I keep the modal open after clicking the submit button to display either a success or error message? I am new to MVC and h ...

Avoiding the storage of POST data in JSON format

Here is some code I am working with: var jsonString = "some string of json"; $.post('proxy.php', { data : jsonString }, function(response) { var print = response; alert(print); }); And this P ...

Lustrous Layout

I am developing a mobile app using titanium where I have a scroll view containing objects that occupy 25% of the screen width. I am attempting to create a 'table' layout with these objects, having 4 columns and multiple rows. Is there a way for t ...

Efficiently encode and decode JSON data between PHP and JavaScript

I am attempting to convert my array results into JSON format and then transmit them to an AJAX success event using JavaScript. PHP $results = array( "time1" => 1, "time2" => 2, ); echo json_encode($results); JAVASCRIPT ...

The jQuery slider does not have the functionality to be dragged

My Ruby on Rails app is utilizing a jQuery slider, but I am encountering an issue where I am unable to drag the slider button. However, it does move successfully if I click anywhere inside the slider. Here is the code snippet: <div id="slider">< ...

Troubleshooting: Issue with running npm start | React app not loading

npm start command seems to be stuck at this particular point - The application is failing to load because of this issue. Here is the content of package.json file - { "name": "reacttest", "version": "0.1.0", & ...

Embrace the flexibility of using Next.js with or without Express.js

Recently, I started the process of migrating a project from create-react-app to next.js. However, I am facing uncertainty when it comes to migrating the backend of the project. Currently, my backend is built with an express server. In next.js, there are p ...