Reputation: 645
I am stuck with a problem with passing data from one page to another page in next.js as I am building a basic news application in which I am fetching get requests from news api and I got results of 10 articles and I mapped them correctly but I want to pass the single article date to a new Page named singleNews. So How can I do it? here is place where I am fetching all 10 articles:
export default function news({data}) {
// const randomNumber = (rangeLast) => {
// return Math.floor(Math.random()*rangeLast)
// }
// console.log(data)
return (
<>
<div>
<h1 className="heading">Top Techcrunch Headlines!</h1>
</div>
<div className={styles.newsPage}>
{ // here you always have to check if the array exist by optional chaining
data.articles?.map(
(current, index) => {
return(
<Card datas={current} key={index+current.author} imageSrc={current.urlToImage} title={current.title} author={current.author}/>
)
}
)
}
</div>
</>
)
}
export async function getStaticProps() {
const response = await fetch(`https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=${process.env.NEWS_API_KEY}&pageSize=12`)
const data = await response.json() // by default Article length is 104
// const articles = data.articles;
return{
props : {
data,
}
}
}
Upvotes: 50
Views: 83342
Reputation: 11
The options here mention mostly passing of a simple data, some (comments) mentioned using context. But you do not always want to pass simple data and using context for this is, in my opinion, not an ideal solution1.
If your use case is similar to mine - you want to avoid refetching data that had already been fetched by parent component - I found out that the best solution for me is using the SWR library (it was created by Next.js developers).
You can even find it mentioned in the official Next.js docs here.
Basically it's a client-side cache that manages key-value pairs, where keys are URLs you fetched and values are the data returned by this fetch. If you then try to refetch the same URL, it will (practically immediatelly) return the cached response.
So in our scenario, you fetch the data in the parent component, and then can fetch as many times as you want in other (bonus: not limited to child) components, basically working as using data from context.
1 Mostly because I find it annoying to specify context everywhere I want to use this logic, but also my spidey-sense is tingling, there are gonna be more gotchas.
Upvotes: 0
Reputation: 1186
Thanks @ivanatias
For NEXT 14 same to send data between page and client
import Link from 'next/link';
const Sender = () => {
return (
<section>
<h1>Sender to server side Receiver </h1>
<Link
href={{
pathname: '/Receiver',
query: {
search: 'AAAA server',
},
}}
>
Go to another page
</Link>
<h1>Sender to client side Receiver </h1>
<Link
href={{
pathname: '/ReceiverClient',
query: {
search: 'BBBB client',
},
}}
>
Go to another page
</Link>
</section>
);
};
export default Sender;
and
const AnotherPage = ({ searchParams }) => {
console.log(searchParams.search); // Logs "search"
};
export default AnotherPage;
for client component
'use client';
import { useSearchParams } from 'next/navigation';
const SomeClientComponent = () => {
const searchParams = useSearchParams();
console.log(searchParams.get('search')); // Logs "search"
const AAAA = searchParams.get('search');
return (
<main className="flex min-h-screen w-full flex-col items-center px-2 sm:px-4 md:px-8">
<p>{AAAA}</p>
</main>
);
};
export default SomeClientComponent;
Upvotes: 0
Reputation: 4033
You can pass data to another page via Link
component this way:
import Link from 'next/link'
<Link
href={{
pathname: '/to-your-other-page',
query: data // the data
}}
>
<a>Some text</a>
</Link>
and then receive that data in your other page using router
:
import { useRouter } from 'next/router'
const router = useRouter();
const data = router.query;
This is also known as putting state in the URL.
Update - Next.js v13+:
Next.js added a new app directory feature which uses React Server Components by default. Since Next.js v13.4.1 the app
directory is now stable and is the recommended way of working with the framework.
Some changes have been implemented on the Link
component and useRouter
hook. Also, some new hooks have been added for client-side use. A brief list of these changes:
It's no longer needed to wrap an a
tag with the Link
component. The new Link
component extends the HTML <a>
element. <a>
tag attributes can be added to Link
as props. For example, className
or target="_blank"
. These will be forwarded to the underlying <a>
element on render.
The new useRouter
hook should be imported from next/navigation
and not next/router
.
The query object has been removed and is replaced by useSearchParams().
Passing data from one page to another using app
directory feature and Server Components:
import Link from 'next/link'
const SomePage = () => {
return (
<section>
<h1>Some page</h1>
<Link
href={{
pathname: '/anotherpage',
query: {
search: 'search'
}
}}
>
Go to another page
</Link>
</section>
)
}
export default SomePage
Receiving the data through searchParams
prop:
const AnotherPage = ({ searchParams }) => {
console.log(searchParams.search) // Logs "search"
...
}
export default AnotherPage
On Client Components:
'use client'
import { useSearchParams } from 'next/navigation'
const SomeClientComponent = () => {
const searchParams = useSearchParams()
console.log(searchParams.get('search')) // Logs "search"
...
}
export default SomeClientComponent
This also works with page components on pages
folder. Don't include the 'use client'
directive in this case.
Upvotes: 79