0

I want to create dynamic pages based on the ID of a Saloon profile using useSWR and useRouter, but the data loads in after the pages are rendered.

This is my code:

import useSWR from "swr";
import { useRouter } from "next/router";

const fetcher = (url) => fetch(url).then((res) => res.json());

export default function FindSaloonProfile() {
  const router = useRouter();
  const { id } = router.query;
  const { data, error } = useSWR(
    id ? `/api/getSaloons` : null,
    id ? fetcher : null
  );

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;

  return <>Hello {data.name} </>;
}

If I console.log(data), it starts getting undefined and loads in the data afterward, but then it is too late, as the page is already rendered.

console

What do I do wrong?

Mathias Riis Sorensen
  • 504
  • 3
  • 13
  • 34

2 Answers2

0

Wrap the fetcher in a function:

const fetcher = (url) =>
  fetch(url).then(
    async (res)=> {
      const result = await res.json();

      if (res.status !== 200) {
        return Promise.reject(result);
      } else {
        return result;
      }
    }
  );
Yilmaz
  • 35,338
  • 10
  • 157
  • 202
0

Next.js is the server-side rendering framework, but mostly SWR works on the client-side merely, so it means API won't fetch data till the page loaded (or Javascript loaded).

Recently, SWR has published a new document for Next.js integration. You can check it out here.

https://swr.vercel.app/docs/with-nextjs

Let me try to keep it in a short explanation

getStaticProps will help you to get data on the server-side

 export async function getStaticProps() {
  // `getStaticProps` is executed on the server side.
  const saloons = await getSaloons() //you can call `fetcher` here too
  return {
    props: {
      fallback: {
        '/api/getSaloons': saloons
      }
    }
  }
}

After that, you need to import SWRConfig for fallback which is for the fetched data (React-Next.js hydration with help you to link your data with React's context)

export default function Page({ fallback }) {
  // SWR hooks inside the `SWRConfig` boundary will use those values.
  return (
    <SWRConfig value={{ fallback }}>
      <FindSaloonProfile />
    </SWRConfig>
  )
}

Lastly, you just have your usual component

import useSWR from "swr";
import { useRouter } from "next/router";

const fetcher = (url) => fetch(url).then((res) => res.json());

export default function FindSaloonProfile() {
  const router = useRouter();
  const { id } = router.query;
  //your data will get from the server initially, and then it will try to fetch again for the update
  const { data, error } = useSWR(
    id ? `/api/getSaloons` : null,
    id ? fetcher : null
  );

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;

  return <>Hello {data.name} </>;
}

Hopefully, my answer is able to help you

Nick Vu
  • 14,512
  • 4
  • 21
  • 31
  • Thanks, Nick. That seems promising. I'll test later today. Just to clarify, are we talking about the same file, or are you adding the different parts into separate files? I'm mostly talking about the Page function example. Should the Page function and getStaticProps live within the [id].js file, and then importing the FindSaloonProfile() ? Another question, should I use getServerSideProps instead? I'm dealing with profiles which could change without rebuilding? – Mathias Riis Sorensen Mar 07 '22 at 17:31
  • If I try to use getStaticProps, it gives me the following error message: `Error: getStaticPaths is required for dynamic SSG pages and is missing for '/find-salon/[id]'. Read more: https://nextjs.org/docs/messages/invalid-getstaticpaths-value` – Mathias Riis Sorensen Mar 07 '22 at 17:45
  • 1
    If your component is a page-level one, you can call `getStaticProps` directly there. Technically, I think `gerServerSideProps` is also good, but I'm not sure how it's integrated well with SWR (please share your experimental result with me after you try it) – Nick Vu Mar 07 '22 at 17:55
  • ah I see, I'll help you to check tomorrow (now it's midnight at my place) – Nick Vu Mar 07 '22 at 17:56
  • Will do that, and thank you for your help. Appreciate it! Sleep well. – Mathias Riis Sorensen Mar 07 '22 at 17:59
  • Do you have `getStaticPaths`. If you have that, you can try to add `fallback: 'blocking'` which is waiting for generated HTML – Nick Vu Mar 08 '22 at 03:23
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/242709/discussion-between-nick-vu-and-mathiassio). – Nick Vu Mar 08 '22 at 05:24