'Next.js Dynamic Page using useSWR
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.
What do I do wrong?
Solution 1:[1]
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;
}
}
);
Solution 2:[2]
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Yilmaz |
| Solution 2 | Nick Vu |

