Dynamic routing with getServerSideProps in Nextjs
I'm trying to learn nextjs. Struggling to work out routing with getServerSideProps
.
Using a free API I have a list of countries displayed on the DOM. I want to dynamically link to a country and data be fetched and displayed for that specific country.
Heres my code so far
const Country = props => (
<Layout>
<h1>{props.country.name}</h1>
<span>{props.country.capital}</span>
</Layout>
);
export async function getServerSideProps(context) {
const { id } = context.query;
const res = await fetch(`https://restcountries.eu/rest/v2/name/${id}`);
const country = await res.json();
console.log(`Fetched place: ${country.name}`);
return { props: { country } };
}
export default Country;
<div className='container'>
<Head>
<title>Countries List</title>
<link rel='icon' href='/favicon.ico' />
</Head>
<Layout>
<main>
<h1>
Countries{' '}
<span role='img' aria-label='world emoji'>
🌎
</span>
</h1>
<ul>
{countries.map(country => (
<li key={country.name}>
<Link href='/p/[id]' as={`/p/${country.name}`}>
<a>{country.name}</a>
</Link>
</li>
))}
</ul>
</main>
</Layout>
</div>
);
export async function getServerSideProps() {
// Call an external API endpoint to get posts.
const res = await fetch('https://restcountries.eu/rest/v2/all');
const countries = await res.json();
// By returning { props: posts }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
countries,
},
};
}
export default Home;
The URL dynamically routes ok. For example, when you click on Afghanistan the URL shows http://localhost:3000/p/Afghanistan
.
My country component however doesn't display anything and undefined
is printed to the terminal.
Example of URL and response from URL: https://restcountries.eu/rest/v2/name/Afghanistan
{
name: "Afghanistan"
}
Apologies if a noob question. Trying to learn nextjs
Solution 1:
export async function getServerSideProps(context) {
const { id } = context.query;
const res = await fetch(`https://restcountries.eu/rest/v2/name/${id}`);
const country = await res.json();
console.log(`Fetched place: ${country.name}`);
return { props: { country } };
}
you are returning a nested object from above function
{ props: { country:country } }
so this prop will be attached to props as like this:
`props.props`
this is how you should implement
const Country = props => (
<Layout>
<h1>{props.props.country.name}</h1>
<span>{props.props.country.capital}</span>
</Layout>
);
UPDATE
In early version of next.js I think updated after version 9, we were not returning from serverside function by using props
. As of now correct way of implementation is
return {
props: {
countries,
},
};
Solution 2:
Just to add to the accepted answer, you could also destructure to make it (imho) more readable. This is entirely optional though
const Country = ({ country }) => (
<Layout>
<h1>{country.name}</h1>
<span>{country.capital}</span>
</Layout>
);