i hope you are having a great day ! i got a question… i’m currently learning next.js 13 and so i thought doing a personal project with it would be a good idea . Currently i’m doing an e-commmerce with Sanity.io as a cms .The problem i got is that im fetching data with an async function , but i want to also use "use State" hook from react to do a nice product images viewer ! the problem i got is that i can’t use a hook inside of an async function ! so please if anyone got a solution to this i would be very pleased since im really new to next.js 13 here is my code and what i want to do
"use client"
import { Product } from '@/component';
import { getProduct, getProducts } from '@/sanity/sanity-utils';
import React, { useState } from 'react';
import { AiOutlineMinus,AiOutlinePlus,AiFillStar,AiOutlineStar} from 'react-icons/ai';
export default async function ProductDetails({ params }) {
const slug = params.product;
const product = await getProduct(slug);
console.log("product",product)
return (
<div>
<div className='product-detail-container'>
<div>
<div className='image-container'>
<img src={product.image[0]} alt="product-image"
className='product-detail-image'
/>
</div>
<div className='small-images-container'>
{product.image.map((item, i) => (
<img
src={item}
alt={`product-image-${i}`}
key={i}
/>
))}
</div>
</div>
what i really want to do is an use State to acces the images array so it shows each image when i click on it
const [index, setIndex] = useState();
<div className='small-images-container'>
{product.image.map((item, i) => (
<img
src={item}
alt={`product-image-${i}`}
key={i}
onMouseEnter={()=> setIndex(i)}
/>
))}
</div>
thank you so much i hope my questions is understandable
i actually dont know what to do honestly , should i bring the data from sanity differently ?
2
Answers
Try loading getProduct via ‘@/sanity/sanity-utils’ using a useEffect.
In the next 13 app router, you need to choose whether a component is a server component (only runs on server) or a client component (runs in browser). Components using hooks such as
useState
must be client components. On the other hand, only server components can beasync
. At the moment you’re trying to use both at the same time, so its invalid.So one option is to turn your existing
ProductDetails
component into a bona fide client component by removing theasync
keyword and moving the fetching intouseEffect
to avoid fetching on every render (or better yet, use a fetching library such as react-fetch or swr).Alternatively, you could make
ProductDetailsFetcher
an async server component which fetches the data, then passes theproduct
as a prop to a client component which does the rendering. Only the client component would haveuseState
.The best option may depend on how
getProduct
is intended to be used – i.e. whether it designed to be run on the client or server.