skip to Main Content

On my client component, I call getBenchmarksByUser() to fetch the data I need:

export default function BenchmarkBrowser({uid}) {
    
    console.log("client uid:", {uid})
    
    // Watch the state of our Benchmarks
    const [benchmarks, setBenchmarks] = useState();
    
    // Send the server a request for our Benchmarks
    
    useEffect(() => {

        console.log("BenchmarkBrowser component is rendered.");

        getBenchmarksByUser(uid).then((res) => {

            console.log("benchmarks received by client", res);
            setBenchmarks(res);

        })
        .catch((err) => {
            console.log("Error!", err);
        });
    }, [uid]);

    return (
        <>
        <h1>benchmark browser...</h1>
        </>
    );
}

On the server component, it queries Firestore and returns the docs in question:

'use server'
import { db } from "@/lib/firebase";
import { query, getDocs, collection, orderBy, limit } from "firebase/firestore";

export async function getBenchmarksByUser(uid) {

    console.log("server received uid:", uid);
    
    const benchmarksQuery = query(
        collection(db, 'users/' + uid + '/benchmarks'), 
        orderBy('created'), 
        limit(5)
    );
    
    await getDocs(benchmarksQuery).then((res) => {
        console.log("server snapshot docs length", res.docs.length)
        return res.docs;
    })
    .catch((err) => {
        console.log("ERROR",err);
        return null;
    })
    
}

What’s bizarre to me is that I KNOW the data has been fetched properly because I can see my console outputs in the server console (screenshot)

But when it’s returned to the client component, it’s undefined! (screenshot)

What’s going on here? Why is my data suddenly undefined?

2

Answers


  1. Chosen as BEST ANSWER

    I figured it out! The problem was, in the Server Component I was returning the result of a promise in .then()

    Storing the result of the promise in a const, and returning it in the next line, fixed the issue.

    NOTE: This code works, but returns a warning in the server console, because I haven't converted the data to a simple object before returning it to the Client Component. (see Passing props from Server to Client Components (Serialization))

    'use server'
    import 'server-only'
    
    import { db, docToJSON } from "@/lib/firebase";
    import { query, getDocs, collection, orderBy, limit } from "firebase/firestore";
    
    export default async function getBenchmarksByUser(uid) {
    
        console.log("server received uid:", uid);
        
        const benchmarksQuery = query(
            collection(db, 'users/' + uid + '/benchmarks'), 
            orderBy('created'), 
            limit(5)
        );
        
        const snapshot = await getDocs(benchmarksQuery);
        
        console.log("returning doc count:", snapshot.docs.length);
    
        return snapshot.docs.map(doc => doc.data());
    }


  2. I believe it’s because your getBenchmarksByUser is async, but you do not await for it.

    Try

    useEffect(() => {
    
        if (!uid) return;
        const getData = async () => {
            const res = await getBenchmarksByUser(uid);
            setBenchmarks(res);
        } 
        getData();
            
    }, [uid]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search