Home > Net >  React not getting API results on first render
React not getting API results on first render

Time:05-05

I'm running into a problem in development where the page finishes loading before the data gets sent from the API. I've tried using asynchronous functions but that doesn't help even though I'm sure it should. I think I might be doing it wrong. Below is an example of a page in my app where I am experiencing this issue:

import React, {useEffect, useState} from 'react';
import { useRouter } from 'next/router';
import axios from 'axios';
import Link from 'next/link';
import { Card,
         Button
 } from 'react-bootstrap';

export default function SingleTour() {
    const [tour, setTour]= useState({});
    const [tourShows, setTourShows] = useState({});

    const router = useRouter();
    const {slug} = router.query;

    useEffect( () => {
        let enpoints = [
            `http://localhost:3000/tours/${slug}`,
            `http://localhost:3000/listshows/${slug}`
        ]

        axios.all(
            enpoints.map((endpoint) => 
            axios.get(endpoint)))
        .then(response => {
            console.log(response)
            setTour(response[0].data)
            setTourShows(response[1].data)
        })
        .catch(error => console.log(error))
    }, [slug])

    console.log(tour);

    return (
         <div className='container'>
             <div>
                <h1></h1>
             </div>

            <h3>Shows</h3>

            <div className='card-display'>
                    {tourShows.data ? (
                        tourShows.data.map(({attributes, id}) => (
                            <Link href={`/shows/${id}`} passHref key={id}>
                                <Card border="secondary" style={{ width: '18rem', margin: '1rem'}}>
                                    <Card.Body>
                                        <Card.Title>Show {id}</Card.Title>
                                            <Card.Text>{attributes.date}</Card.Text>
                                            <Card.Text>{attributes.location}</Card.Text>
                                            <Card.Text>Head Count {attributes.headcount}</Card.Text>
                                    </Card.Body>  
                                </Card>               
                            </Link>
                ))
            ) : 'LOADING ...'}

            </div>
        </div>
    )
}

Any help is greatly appreciated. I am also using Next JS if that makes a difference.

CodePudding user response:

If you use useEffect hook it is expected that you will have a render before the hook fires to fetch the data, that is the way useEffect works.

If you want to fetch your data inside the next app you have to use getServerSideProps instead, fetch the data there and pass that as a prop to the component. See the docs here: https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props

CodePudding user response:

This is the way React works. useEffect will attempt to fetch the data and React will continue doing it's business, render the component. You can put an if statement at the beginning of the return statement, for instance checking the length of the tourShows.data, it the length is 0 return nothing, otherwise return as you do now.

  • Related