Home > Blockchain >  Fetching Data on useEffect
Fetching Data on useEffect

Time:04-08

Consider the following block of code:

import React from 'react';
import Card from './components/Card';
import './App.css';
import Buttongrp from './components/Buttongrp';
import { useEffect, useState } from 'react';

function App() {
    useEffect(() => {
        fetch('https://reqres.in/api/users')
        .then(response => response.json())
        .then(data => { setDataArray(data); console.log(dataArray) });
    }, []);
    const [cardImgUrl, setCardImgUrl] = useState("https://i.pinimg.com/564x/a0/d5/c9/a0d5c9af2eee2970a6eea591fade8271.jpg")
    const [firstName, setFirstName] = useState("")
    const [lastName, setLastName] = useState("")
    const [email, setEmail] = useState("")
    const [dataArray, setDataArray] = useState([])
    return (
        <>
            <div className="container d-flex my-3">
                <div className="display-4 mx-auto d-inline">CV Screener</div>
            </div>
            <div className="container-fluid my-3">
                <Card cardImgUrl={cardImgUrl} firstName={firstName} lastName={lastName} email={email} />
            </div>
            <div className="container">
                {dataArray.data.map(() => return <Buttongrp />})}
            </div>
        </>
    );
}

export default App;

What i want the page to do is, when the page loads, it should fetch the data using fetchapi , then render the rest of the components. Right now i am getting a Uncaught TypeError: Cannot read properties of undefined (reading 'map') error. I tried but am unable to fix the error.

CodePudding user response:

You can use this condition fr example:

{ dataArray?.data &&
  dataArray.data.map(() => {
    return <Buttongrp />
})

}

CodePudding user response:

You set dataArray to have an empty array as default value but in the render function you access it like an object e.g. dataArray.data.

If the data coming from the API is an object, then you should initialize the state with an empty object.

If the data coming from the API is an array, then you should omit the .data in the render function so the .map is invoked from the actual array.


Adding a condition like @Vedant Shah already mentioned also helps by preventing such errors in the live environment

CodePudding user response:

I always use the loading state and display a loader in such cases. I would recommend to do the following way

  1. Use a loading state const [isLoading, setLoading] = useState(true) Initialise this with true value, then switch to false inside the response function

  2. Add a loading component before the actual return statement, this way, the main statement is not executed if the component is not ready

Just before the return statement, add the following

if (true === isLoading) {
    return(<div> Loading, please wait... </div>)
}
return (
    <>
        <div className="container d-flex my-3">
            <div className="display-4 mx-auto d-inline">CV Screener</div>
        </div>
        <div className="container-fluid my-3">
            <Card cardImgUrl={cardImgUrl} firstName={firstName} lastName={lastName} email={email} />
        </div>
        <div className="container">
            {(dataArray?.data || []).map(() => return <Buttongrp />})}
        </div>
    </>
);

This will guarantee that the main return statement will always contain the data.

  1. If the response returned from server will not contain an empty array in case of no result found, I will usually loop it the following way (dataArray?.data || []).map() in this case, if dataArray does not contain the "Truth" value, it will fallback to empty array, which will avoid the error, you can also extend the logic to make sure dataArray?.data is always an array.
  • Related