The issue of linking .then() functions

I've been struggling to grasp the concept of Promises/then-ables for a while now. Currently, I am working with NextJS.

My goal is to chain together the following steps:

  1. Retrieve data from an API
  2. Save the data
  3. Modify the data to create a component (without causing an infinite loop)

I'm facing difficulty in obtaining the correct data for step #3. Despite trying different approaches, I seem to be stuck at this stage.

For this purpose, I am utilizing the useEffect hook, although I acknowledge there might be alternative methods available as well: https://nextjs.org/docs/basic-features/data-fetching/client-side

export default function Survey() {
  const [dataDB, setDataDB] = useState('');
  let roles;

  function createCards(rolesArr) {

    let role1 = tabs.find(x => x.id == rolesArr[0])
    let role2 = tabs.find(x => x.id == rolesArr[1])
    let role3 = tabs.find(x => x.id == rolesArr[2])

    // the above is null
    // the below is also null:
    //     let role1 = tabs.find(x => x.id == dataDB[0])

    roles.push(role1)
    roles.push(role2); 
    roles.push(role3); // component will map over these 3
  }

  useEffect(() => {
    fetch('example.com/api')
      .then((response) => response.json()) // 1. Retrieves an array like [0, 3, 5]
      .then((data) => {
        setData(dataDB) // 2. Utilizing hook to setData, data will be stored in the database later
      }
     .then((rolesArr) => createCards(rolesArr)) // 3. Modifying data for the component
    })
  )  

  return ( 
    { 
      roles.map((path) => (
        <Card key={path.id}>
          <Text>{path.title}</Text>
        </Card>
      ))
    } 
  )
}

Answer №1

You seem to be facing quite a few issues.

Undefined Roles

let roles; initializes a variable with the value of undefined.

When you try to use it as an array later on, such as in roles.map((path) => ( you will encounter an error.

To resolve this, ensure you define it as an array from the start.

A Tiny Typo

.then((data) => {
        setData(dataDB) // 2. Using hook to setData, will store in database later
      }

You are missing a closing parenthesis at the end there.

Undefined rolesArr

The value returned by:

.then((data) => {
        setData(dataDB) // 2. Using hook to setData, will store in database later
      }

… is undefined because there is no explicit return statement. Therefore, subsequent then() callbacks will receive undefined.

There's no need for an additional promise creation here since what you want can be done within the existing function.

  .then((data) => {
    setData(dataDB);
    createCards(dataDB);
  });

Creating Cards Issue

 roles.push(role1)
 roles.push(role2); 
 roles.push(role3); // component will map over these 3

You face a similar problem here with roles being undefined and not an array.

Moreover, because createCards is executed asynchronously, this code runs after roles.map((path) => (, rendering the changes ineffective.

Instead of mutating a non-existent array, create a new one and store it in state. State updates trigger re-renders, enabling the component to access and iterate over the array.

A typical solution involves:

const [roles, setRoles] = useState(null);

function createCards(rolesArr) {
    // etc
    setRoles([role1, role2, role3]);
}

// etc

if (roles === null) {
    return <p>Loading</p>;
}

return roles.map(etc etc);

Answer №2

When working with the .then() method, it is important to ensure that you return the output from the previous callback function in order to chain multiple .then() calls together. Here's a quick example:

fetchData()
  .then((response) => {
    console.log(response.json())
    return response.json()
  }).then((values) => {
    console.log(values)
    return values.filter((value) => value > 0)
  }).then((positiveValues) => {
    console.log(positiveValues)
    return positiveValues;
  })

In this scenario, the response.json() is printed and then passed on as a value for the subsequent .then() callback to utilize.

To adapt this for your situation, make sure to return the desired value within the second callback like so:

fetch('example.com/api')
      .then((response) => response.json()) // 1. Retrieves an array such as [0, 3, 5]
      .then((data) => {
        setData(dataDB) // 2. Utilizing hook to store data in database at a later point
        return dataDB;
      }).then((rolesArr) => createCards(rolesArr)) // 3. Adjusting data for component usage
    })

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

Unable to sign out user from the server side using Next.js and Supabase

Is there a way to log out a user on the server side using Supabase as the authentication provider? I initially thought that simply calling this function would work: export const getServerSideProps: GetServerSideProps = withPageAuth({ redirectTo: &apos ...

Click the navigation bar to toggle it on and off

I have a script that creates a navbar. Currently, the dropdown menu only opens when hovered over. The issue arises when accessing this on a mobile browser, as the dropdown menu does not open. How can I modify this script to make the dropdown menu open wh ...

angular: the world of guarantees and assistance

I'm struggling to grasp the concept of promises. I understand what they are supposed to do, but when it comes to writing or debugging them, I hit a roadblock. MyController.js (function() { angular.module('WizmoApp').controller('St ...

Executing an asynchronous action without linking promises to subsequent actions

Encountered a challenge while using componentWillReceiveProps with redux async action. Below is the code snippet along with an explanation: componentWillReceiveProps(nextProps) { if(nextProps.job.status === 'applied'){ this.showAppliedDial ...

The issue of the fixed navbar overlapping the scrollbar of the page occurs when utilizing the overflow-y scroll feature

I am trying to create a web page with snap scroll and a fixed navbar that remains at the top. However, I'm facing an issue where the navbar is overlapping the right scroll bar, which should not be happening. If I remove the overflow-y property from th ...

Unable to allocate a second item to an existing one

Encountering an unusual issue while trying to assign an item a second time. Initial scenario: I am working with a jqxTree containing various items as shown below: - apple - oracle - microsoft When I drag and drop one item into another, the structure loo ...

Combining two HTML tables using jQuery/JavaScript

My table is displayed below: <table id="first" class="merge"> <tr> <td>Mick Jagger</td> <td>30</td> <td>50</td> <td>10</td> </t ...

Using Facebook authentication in React Native

Currently developing a React Native app and aiming to incorporate Facebook login functionality. The back-end logic for user authentication is handled by an API in Node.js. Utilizing passport.js to enable users to log in using either Facebook or Email cre ...

expanding the expressjs res feature

I am currently working on implementing an error and notification feature for my expressjs app. My approach was to add a function by calling: app.use(function (req, res, next) { res.notice = function (msg) { res.send([Notice] ' + msg); } }); ...

Troubleshooting React and NodeJs Fetch Problem

I am currently working on retrieving data from my API, which is functioning properly. The API endpoint I am trying to fetch results from is http://localhost:5000/api/continents. {"data":[{"continentId":3,"CName":"Atlantis"},{"continentId":2,"CName":"Devia ...

Processing JSON in PHP after an AJAX POST request

In the scenario where JavaScript is used to make an ajax request: index.js- var dataFeedback = $("#feedback_popup_message_body").val(); var jsonObj = JSON.stringify({dataFeedback: dataFeedback}); $.ajax({ url: "index.php", type: 'POST' ...

What is the best way to change the date format from "yyyy-MM-dd" in a JavaScript file to "dd/MM/yyyy" and "MM/dd/yyyy" formats in an HTML file?

Is there a way to transform the date string "2020-08-02" from a JavaScript file into the formats "08/02/2020" and "02/08/2020" in an html file, without relying on the new Date() function in JavaScript? I would greatly appreciate any assistance with this t ...

Button cannot be activated upon selecting a row

The goal is to activate a button when a row is selected. However, the button remains disabled even after selecting a row. Below is a snippet of the code as well as a screenshot showing the issue [error_1]: onInit: function () { var oViewMode ...

Can you provide a guide on how to retrieve an HTML file using JSON?

There is a problem with fetching files in different formats. Specifically, I want to retrieve an HTML file that needs to be embedded in an iFrame. Currently, my AJAX request only retrieves SWF files. Is there a way to call and fetch the HTML file instead ...

What is the best way to confirm checkbox selection based on MySQL data?

Writing this question feels challenging, but I have a collection of checkboxes with their data stored as JSON in my PHP database. What I'm trying to achieve now is to dynamically load the JSON data on the page without refreshing it, checking specific ...

Send all visitors from a subdomain to NextJS

I am trying to direct all traffic from a subdomain directly to my pricing page instead of the homepage, but I am struggling with incorporating wildcards into the 'has' value. The syntax I have attempted is as follows: // next.config.js module.ex ...

The Angular ViewportScroller feature appears to be malfunctioning in the latest release of Angular,

TestComponent.ts export class TestComponent implements OnInit, AfterViewInit { constructor( private scroller: ViewportScroller, ) {} scrollToAnchor() { this.scroller.scrollToAnchor('123456789'); } } HTM ...

Identifying an Android device using Javascript or jQuery

Is there a way to identify an Android device for styling a mobile website? I want to add specific CSS styles for users on the Android platform. Appreciate any help! ...

Error: Webpack encountering reference errors when handling multiple entry points

Here is my setup in webpack.config.js: entry: { a:'./src/a.js', b:'./src/b.js' }, output: { path: path.join(__dirname, 'dist'), filename: '[name].bundle.js' } The content of a.js includes: const ...

Whenever signing in with Next Auth, the response consistently exhibits the values of "ok" being false and "status" being 302, even

I am currently using Next Auth with credentials to handle sign-ins. Below is the React sign-in function, which can be found at this link. signIn('credentials', { redirect: false, email: email, password: password, ...