I am trying to send an id
to the next page when the user navigates.
I have a homepage where I am fetching an Array of data and using .map
to display it in a kind of card-based UI.
Now, when the user clicks the card, they will be navigated to the next page display details about that card.
Suppose the home page is here - localhost:3000
And user clicks the card with an id of 234
They will be navigated to the next page as :
The next page is as - localhost:3000/user/234
Now here I want to display information about that card with an id of 234. FOr that I do need to make a fetch request as such fetch(https://userdatabase/234
)
The above 234
is a dynamic id for sure, How can I let this fetch
request know to change this id every time a new card has been clicked? Or in other words, How this page "knows" the id of the card ?
Right now, I', using a workaround as :
- When the user is at the second page, the URL will be like this
localhost:3000/user/386
- Get this id in NextJS using
useRouter
as :
import {useRouter} from 'next/router'
`const router = useRouter()`
fetch(`localhost:3000/user/${router?.query?.user})
I understand taking id from URL and making a fresh quest is not ideal at all and this is causing stale caching issue on the second page.
How do I resolve this in a better way?
Thanks so much for reading.
CodePudding user response:
you need to make a dynamic route : Next.js Docs
for your case make a file pages/user/[id].js
1. Client side
access id with this snippet :
import { useRouter } from 'next/router'
const Component = () => {
const router = useRouter()
const { id } = router.query
return <p>{id}</p>
}
export default Component
2. Server side
you can use it any of the data fetching functions
Snippet for SSR :
export async function getServerSideProps({ params }) {
const { id } = params
// fetch data from database with id
return {
props: {}, // will be passed to the page component as props
}
}
More on what gets passed to data fetching functions as Context : Context Parameter
CodePudding user response:
Add id
to the dependencies array of useEffect()
.
Something along these lines:
import { useState, useEffect } from "react";
import { useRouter } from 'next/router';
function Page() {
const router = useRouter();
const [page, changePage] = useState();
// `query` can only be fully parsed client-side
// so `isReady` flag is needed
const { query, isReady } = router;
const { id } = query;
// also need to parse the query value to undefined or string
const parsedID = id === undefined
? undefined
: Array.isArray(id)
? id[0]
: id;
useEffect(() => {
// refuse to run the effect if query is not ready
// or ID is undefined
if (!isReady || !parsedID ) {
return;
}
// this looks ugly
// but pure promise syntax is even uglier
// and `useEffect()` doesn't accept async functions
(async () => {
// errors are assumed to be handled in the `_app` component
// so no error-handling logic here
const response = await fetch(`localhost:3000/user/${parsedID}`);
const newPage = await response.json();
changePage(newPage);
})()
}, [isReady, parsedID]);
return (
<>
{!page
// show loading placeholder until the page is fetched
? <div>Loading...</div>
// pass the `page` value to whatever component you need
: ...
}
</>
)
}
export default Page;