Preloading getServerSideProps data with Next.js?

Viewed 14797

I've got a simple React component:

const Page = ({ data }) => {
    return (
        <header>
        {data.length !== 0 ?
          <>
            {data((d) =>
              // render data
            )}
          </>
          :
          <>Loading...</>
        }
        </header>
      )
    }

I'm getting the data using Next.js recommended getServerSideProps:

export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`someurl`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

Now, for the love of God, I can't figure out why <>Loading...</> is never rendering. The page is blank and then everything pops up. Why does it happen and how do I fix that? of course data.length IS 0 before it's fetched...

Note I'm using dynamic routing and do not want to go with getStaticProps.

3 Answers

It's obvious that user should not wait a few seconds in which nothing happens (because getServerSideProps is not finished loading) when he clicks a link. He should see some action is happening, for example:

  • Loading spinner
  • Data template (boxes for images, text and so on), youtube example.

But for now it's not possible with getServerSideProps, because page is rendered only after getServerSideProps request is complete.

There is exist future request on next.js about this, so i hope it will be implemented.

you need to use isFallback method provided by there next/router. have a look on this code try to look for isfallback https://github.com/vercel/next-site/blob/master/pages/docs/%5B%5B...slug%5D%5D.js.

Edit: 

`export async function getServerSideProps() {
  Fetch data from external API
  const res = await fetch(someurl)
  const data = await res.json()

   Pass data to the page via props
  return {
        props: res ? {
            data,
            id,
            url,
        } : {}
    };
}
`


and in your component

    const router = useRouter();
    const { isFallback } = router
    if (isFallback) {
        return <Loading />
    }
    else {
        return (
            // render data
        )
    }
Related