When attempting to fetch data with a dynamic URL in next.js, the error message "undefined is returned

While fetching data on my main page everything works as expected. However, when trying to fetch data in another folder using the same code but with a dynamic URL, I encounter an error when attempting to use methods on an array. Interestingly, when I console.log the fetched data, it displays the same array as on my main page.

If I remove the Link and only focus on book.title, it works fine. But I face an error when trying to retrieve data from resources.

DataFetcher.js
const [data, setData] = useState(null);
const [isLoading, setLoading] = useState(false);

useEffect(() => {
  setLoading(true);
  fetch('https://gnikdroy.pythonanywhere.com/api/book')
    .then((res) => res.json())
    .then((data) => {
      setData(data);
      setLoading(false);
    });
}, []);

return(
       <div>
        {data.results.map((book, index) => (
          <div key={index}>
            <h1>{book.title}</h1>
              <h2>
                {
                  book.resources.find(
                    ({ type }) => type === 'application/epub+zip'
                  ).uri
                }
              </h2>
          </div>
        ))}
      </div>
)
ResourceFetcher.js
const router = useRouter();
const { name } = router.query;
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);

useEffect(() => {
  setLoading(true);
  fetch(`https://gnikdroy.pythonanywhere.com/api/book/?search=${name}`)
    .then((res) => res.json())
    .then((data) => {
      setData(data);
      setLoading(false);
      console.log(data);
    });
}, []);

return(
      <div>
        {data.results.map((book, index) => (
          <div key={index}>
            <h1>{book.title}</h1>
              <h2>
                {
                  book.resources.find(
                    ({ type }) => type === 'application/epub+zip'
                  ).uri
                }
              </h2>
          </div>
        ))}
      </div>
)

Console log output inside DataFetcher.js

Answer №1

Sometimes, your response data may not have the necessary fields for resources.
This can result in book.resources being undefined or null.

To handle this situation easily, you can utilize Optional Chaining(?.)

Instead of:

{
   book.resources?.find(
     ({ type }) => type === 'application/epub+zip'
   )?.uri || ''
}

Answer №2

Aside from Wu Woo's response, when considering how React processes your code,

First, the return statement will be executed followed by the useEffect hook only during page load if there are no values in the dependency array of useEffect.

In your case, you initially have data = null during page load. Therefore, when rendering the following code snippet, since data = null, data.results cannot be used with Arrays.map().

Subsequently, the useEffect hook will be executed where the value returned from an API call is set as the new value for data.

To avoid the error of rendering undefined, it is crucial to ensure that data.results is not equal to null/undefined, and only render when there is a valid value for data.results.

This can be achieved through the following methods:

  1. Utilize the optional chaining operator (?.) like in Wu Woo's answer, which simplifies accessing values within connected objects in cases where references or functions may be undefined or null. This prevents errors when book.resources is null/undefined.

  2. Render content only when there are valid values for both data.results and book.resources, otherwise do not render anything as shown below:

    // Conditionally check if there is a value for data?.results before rendering.
    {data?.results && data.results.map((book, index) => (
      <div key={index}>
        <h1>{book.title}</h1>
        <Link href={`/reader/${book.id}`} passHref>
          <h2>
            {/* Conditionally check if there is a value for book?.resources before rendering this part. */}
            {book?.resources &&
              book.resources.find(
                ({ type }) => type === 'application/epub+zip'
              ).uri
            }
          </h2>
        </Link>
      </div>
    ))}
    

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

How can jQuery identify the elements that the selected text spans across?

In the midst of a project, I find myself in need of extracting specific text within an iframe. This text may traverse across multiple spans within the iframe, each identified by a unique ID spanning from 1 to the end of the page. My goal is not to retrie ...

Protractor: Moving further down the page

One issue I encountered is with a button on my page that becomes visible only when the user scrolls down. As a result, Protractor tests are throwing an error: UnknownError: unknown error: Element is not clickable at point (94, 188). I attempted to reso ...

Unable to load files in Handlebars when using Node and Express

Currently, I am in the process of developing a Node/Express web application for basic CRUD operations. However, I am encountering difficulties incorporating Handlebars into my project. Whenever I attempt to utilize Handlebars, none of the stylesheets from ...

Weekly downloads for NPM show no activity

https://i.stack.imgur.com/4Uhk4.png https://i.stack.imgur.com/0vikS.png Why are all the weekly downloads showing zero for npm packages? I'm new here and confused about why this is happening, any insights? If you could please help me open this issue ...

Using React for Right-to-Left (RTL) Support

How can RTL (Right-to-Left) support be effectively implemented in React applications? Is there a method to customize default <p> and <span> components for RTL support without the need to rewrite existing components? For instance, using a global ...

Using the jQuery before() method to manipulate form fields

Is it possible to utilize the jQuery before method to insert a form? An example scenario could be as shown below: <script> $(document).ready(function() { $("button").click(function() { $("button").before('<form><input type="text ...

Type property is necessary for all actions to be identified

My issue seems to be related to the error message "Actions must have a type property". It appears that the problem lies with my RegisterSuccess action, but after searching on SO, I discovered that it could be due to how I am invoking it. I've tried so ...

Is it possible for an object to receive notifications when a component object undergoes changes in Angular 2/4?

When working with Angular components, it's possible to pass a variable or object as @Input(). The component will be notified whenever the value of this input changes, which is pretty cool... I'm currently developing an application that features ...

Securing user authentication in Spring Boot and NextJs: A guide for managing two distinct user types

I am new to dealing with authentication and finding myself at a standstill on the best, most secure approach. Here's an overview of my current setup: Utilizing Spring Boot for the backend/REST API and NextJs for the frontend. We require two types of ...

Executing multiple jQuery Ajax requests with promises

I've been learning how to use promises gradually, and now I'm faced with the challenge of handling multiple promises. In my code snippet, I have two email inputs in a form that both create promises. These promises need to be processed before the ...

Exploring Sanity npm package with Jest for mocking tests

I am encountering an issue with mocking some code in my sanity.ts file: import sanityClient from '@sanity/client'; // eslint-disable-next-line @typescript-eslint/no-var-requires const blocksToHtml = require('@sanity/block-content-to-html&ap ...

Is there a specific side effect that warrants creating a new Subscription?

Recently, I had a discussion on Stack Overflow regarding RxJS and the best approach for handling subscriptions in a reactive application. The debate was whether it's better to create a subscription for each specific side effect or minimize subscriptio ...

Is Selenium suitable for testing single page JavaScript applications?

As a newcomer to UI testing, I'm wondering if Selenium is capable of handling UI testing for single-page JavaScript applications. These apps involve async AJAX/Web Socket requests and have already been tested on the service end points, but now I need ...

modify header when button is clicked

I am trying to create a JavaScript function that will update the name of an HTML table header when a button is clicked. However, I am having trouble accessing the text content within the th element. document.getElementById("id").text and document.getEl ...

What is the process for ordering by a many-to-many relationship in Sequelize?

I am dealing with a many-to-many relationship between User and Category, connected through the UserCategory model. Here is the code snippet illustrating this relationship: let user = await User.findAll({ where: { id: req.query.user }, attribut ...

maximum number of results in google custom search limit

I'm trying to retrieve the top 40 results from the Google API, but when I limit the result using the code below, it doesn't seem to work. How can I achieve getting the top 40 results with the Google API? <script> (function() { ...

A comprehensive guide on converting an array of custom objects into JSON using Swift 4

I am currently in the process of preparing parameters to be sent to a server. This involves converting my array of custom objects into JSON format. Here is what I have attempted: let data = try? JSONSerialization.data(withJSONObject: fastForm.route, opti ...

Guidelines for implementing a seamless transition effect on elements with Tailwind CSS

I successfully created a responsive nav bar using Tailwind CSS in Next.js, and it is functioning perfectly. https://i.stack.imgur.com/yTCbs.png https://i.stack.imgur.com/rdXhL.png https://i.stack.imgur.com/J8fM6.png Everything works well, except when I ...

"Trouble with Angular's http.get method failing to retrieve data from MySQL through Node

I am struggling to retrieve data from MySQL using Angular and Node.js. Despite trying, I am unable to make it work. When I check Postman using the link http://localhost:8080/locations, I can see the data. { "status": "200", "items": [ { "cit ...

The array within the document is unable to perform $push, $pull, and $inc operations simultaneously

In my collection, each document follows this format: { "_id": "57e81e0d5891000c99cc133b", "name": "service_name", "use": 8, "errors": [], } The errors field may contain objects like: { "e": { "error": "socket hang up" }, "d": "2016-10- ...