Next.js Discord

Discord Forum

Passing Object Array to Client Side Component

Answered
Horned oak gall posted this in #help-forum
Open in Discord
Horned oak gallOP
Currently I am grabbing an array of listings using an async function and want to pass this to a client component to map. The issue being I cannot .map() the dataArray into the client component nor is it allowing me to keep my client component as a client component if I just map the dataArray straight into the client component.

(some code redacted to keep the post smaller)
(server component)
export default async function Listings({ searchParams }) {
    const listingsData: Promise<Listing[]> = getAllListingsForEvent(event.eventId);

    return (
        <section className="">
            <div>
                <ul className="grid xl:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 grid-cols-1 gap-10 my-10 px-10 w-full flex flex-wrap justify-center">
                    <SwapListing promise={listingsData}/>
                </ul>
            </div>
        </section>
    )
}


(client component)
export default async function SwapListing({ promise }: Props) {
    const listings = await promise;



    console.log(listings)
    const content = listings.map(listing => {
        // const [counter, setCounter] = useState(0);
        const imagesLength = listing.images.length;

        // const nextImage = () => {
        //     if (counter + 1 > imagesLength - 1) {
        //         setCounter(0);
        //     } else {
        //         setCounter(counter + 1);
        //     }
        // };
        //
        // const backImage = () => {
        //     if (counter - 1 < 0) {
        //         setCounter(imagesLength - 1)
        //     } else {
        //         setCounter(counter - 1);
        //     }
        // };

        return (
            <div className="flex flex-row justify-center">
                {/*<button className="px-3 mt-48 rounded-3xl max-h-10 text-4xl flex-none hover:bg-rtOrange" onClick={nextImage}>*/}
                {/*    &lt;*/}
                {/*</button>*/}
                <div className="flex flex-col rounded-xl border border-rtBlack border-2 max-w-md flex-grow hover:opacity-80">
                    <Link href={`/swaps/${listing.event.eventId}/listings/${listing.listingId}`}>
                        <div className="px-4 py-2 text-2xl truncate bg-rtBlue font-black rounded-t-lg">{listing.listingTitle}</div>
                        <div className="flex flex-col">
                            <div className="relative h-80 max-w-md">
                                <Image
                                    src={listing.images[0]}
                                    className="object-cover"
                                    quality={80}
                                    fill
                                    alt="Frag Swap listing image"
                                />
                            </div>
                        </div>
                        <div className="flex flex-row justify-between px-4 py-2">
                            <p>Price:</p>
                            <p>$ {listing.price}</p>
                        </div>
                        <div className="flex flex-row justify-between px-4 py-2">
                            <p>Available:</p>
                            <p>{listing.quantity}</p>
                        </div>
                        <div className="flex flex-row justify-between px-4 py-2">
                            {/*<p>Seller:</p>*/}
                            {/*<p>{identityName}</p>*/}
                        </div>
                    </Link>
                </div>
                {/*<button className="px-3 mt-48 rounded-3xl max-h-10 text-4xl flex-none hover:bg-rtOrange" onClick={backImage}>*/}
                {/*    &gt;*/}
                {/*</button>*/}
            </div>
        )
    })

    return content;
}


I have use client , and the useState commented out currently
Answered by Plague
Wait I'm confused, you're using async/await in the client component section? That's not supported.

You have to either:
1. resolve the promise in the server component by awaiting it
2. read the value of the promise using the [use](https://react.dev/reference/react/use) API in the client component (caveats may apply so please read the documentation)
View full answer

7 Replies

Wait I'm confused, you're using async/await in the client component section? That's not supported.

You have to either:
1. resolve the promise in the server component by awaiting it
2. read the value of the promise using the [use](https://react.dev/reference/react/use) API in the client component (caveats may apply so please read the documentation)
Answer
Sounds like I may just need to add await right before “getAllListingsForEvent”? On mobile but will try this tomorrow
@Horned oak gall The async/await is in the server component(first code block), which then I pass into <SwapListing />
directly under "(client component)" you have this code:
 export default async function SwapListing({ promise }: Props) {
    const listings = await promise;
you cannot do that in a client component, in the server component code block you showed, you use the async keyword but you don't await anything, you just initialize the promise
@Plague you cannot do that in a client component, in the server component code block you showed, you use the `async` keyword but you don't await anything, you just initialize the promise
Horned oak gallOP
ahhh I should of removed those before posting my bad... They weren't there originally but I had them there to test other features for a bit.
Horned oak gallOP
Anyways here is the up to date working version now

export default async function Listings({ searchParams }) {

    let event: Event = JSON.parse(searchParams.event);
    console.log(event.eventId)
    const listingsData: Promise<Listing[]> = await getAllListingsForEvent(event.eventId);

    return (
        <section className="">
            <div>
                <ul className="grid xl:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 grid-cols-1 gap-10 my-10 px-10 w-full flex flex-wrap justify-center">
                    {(await listingsData).map((listing) => (
                        <SwapListing listing={listing} key={listing.listingId}/>
                    ))}
                </ul>
            </div>
        </section>
    )
}


"use client"
import Image from "next/image";
import Link from "next/link";
import React, { useState } from "react";

export default function SwapListing({ listing }) {

    const [counter, setCounter] = useState(0);
    const imagesLength = listing.images.length;

    const nextImage = () => {
        if (counter + 1 > imagesLength - 1) {
            setCounter(0);
        } else {
            setCounter(counter + 1);
        }
    };

    const backImage = () => {
        if (counter - 1 < 0) {
            setCounter(imagesLength - 1)
        } else {
            setCounter(counter - 1);
        }
    };

    return (
        <div className="flex flex-row justify-center">
            <button className="px-3 mt-48 rounded-3xl max-h-10 text-4xl flex-none hover:bg-rtOrange" onClick={nextImage}>
                &lt;
            </button>
            <div className="flex flex-col rounded-xl border border-rtBlack border-2 max-w-md flex-grow hover:opacity-80">
                <Link href={`/swaps/${listing.event.eventId}/listings/${listing.listingId}`}>
                    <div className="px-4 py-2 text-2xl truncate bg-rtBlue font-black rounded-t-lg">{listing.listingTitle}</div>
                    <div className="flex flex-col">
                        <div className="relative h-80 max-w-md">
                            <Image
                                src={listing.images[counter]}
                                className="object-cover"
                                quality={80}
                                fill
                                alt="Frag Swap listing image"
                            />
                        </div>
                    </div>
                    <div className="flex flex-row justify-between px-4 py-2">
                        <p>Price:</p>
                        <p>$ {listing.price}</p>
                    </div>
                    <div className="flex flex-row justify-between px-4 py-2">
                        <p>Available:</p>
                        <p>{listing.quantity}</p>
                    </div>
                    <div className="flex flex-row justify-between px-4 py-2">
                        {/*<p>Seller:</p>*/}
                        {/*<p>{identityName}</p>*/}
                    </div>
                </Link>
            </div>
            <button className="px-3 mt-48 rounded-3xl max-h-10 text-4xl flex-none hover:bg-rtOrange" onClick={backImage}>
                &gt;
            </button>
        </div>
    )
}