0

I have multiple getServerSideProps in my project and I have a header which displays pages and I have to wait for a page to be opened once I click upon it since I need data to be fetched. Once they are fetched the page will be open.

One approach I used to show user a loading state is to use routeChangeStart BUT I stumbled upon one problem and so I would like not to use this case.

If I go on a page and the data is fetching I want to show user a spinner or some indicator and once the data is fetched I want to stop the indicator/spinner.

Rostyk
  • 939
  • 3
  • 13
  • 32

2 Answers2

0

As you probably figured out, getServerSideProps runs on the server and is blocking. The fetch request needs to complete before the HTML is sent to the user (i.e., the page is changed). So if you want to show a loading indicator, you need to move that fetch request to the client.

For instance, if you probably have a page with this basic structure:

export default function Page({ data }) {
  return <div>{data.name}</div>
}

export async function getServerSideProps() {
  const response = await fetch('https://example.com/api')
  const data = await response.json()
  return {
    props: { data },
  }
}
const fetcher = url => fetch(url).then(res => res.json());

export default function Page() {
  const { data } = useSWR('https://example.com/api', fetcher)

  if (!data) return <LoadingSpinner />
  return <div>{data.name}</div>
}

Or if you don't need SWR and can use a simple fetch request:

export default function Page() {
  const [data, setData] = useState()

  useEffect(() => {
    fetch('https://example.com/api')
       .then(async(response) => {
          const json = await response.json()
          setData(json)
       })
  })

  if (!data) return <LoadingSpinner />
  return <div>{data.name}</div>
}

P.S. If the initial fetch request in getServerSideProps used sensitive information (e.g., API secret credentials), then go ahead and setup a Next.js API route to handle the sensitive part and then fetch the new route.

Nick
  • 5,108
  • 2
  • 25
  • 58
  • Thanks for the help, but I used ssr not just for fetching but for SEO, you approach is correct but it removes seo from my page. – Rostyk Aug 11 '21 at 09:07
0

I just used routeChangeStart.

I didn't want to use it since router.push('/map') didn't work in pages/index.tsx file but I solved this issue by creating a new component putting router.push in useeffect and rendering a loader.

routeChangeStart was in _app.js and because of this in index.js router.push() didn't work - I tested it

routeChangeStart - how it works?

When we click on a page the data is being fetched on the server and the page will only be displayed to us once the data is fetched. So we can make the next thing, we can just intercept the route change.

When we click on a link(we wait for data to fetch) we set loading state in routeChangeStart to true and if we moved to another page(it means we fetched the data) we invoke routeChangeComplete which runs once we moved to the route we wanted to, and here we set loading state to false. And after this I just pass the loading state using React Context

Rostyk
  • 939
  • 3
  • 13
  • 32