reactjsnext.js

How to get querystring/search params to be used in an useEffect?


I am trying to get a search param (id) from the url to be used in a REST API call (client.adsGET2).

The problem I am facing is that the id is only set after the API call has been executed. How can I get the search param into the useffect function?

"use client"; // This is a client component  

import { useState, useEffect, Suspense } from 'react';
import { Client } from '@/generated/generated_admanager_client';  
import withAuth from '@/components/with-auth';
import { GetAdDto } from '@/generated/generated_admanager_client';
import { useRouter, useSearchParams } from 'next/navigation';
function AdElement(ad: GetAdDto) {  
    return (  
        <li key={ad.ulid}>  
            <h2>{ad.title}</h2>  
            <p>{ad.description}</p>  
            <p>{ad.creationDate?.toString()}</p>  
        </li>  
    );  
}  

function GetAd() {  
    const router = useRouter();
    const [ad, setAd] = useState<GetAdDto>();
    const [error, setError] = useState<string | null>(null);
    let id;
    console.log('1');

    function Search() {
        const searchParams = useSearchParams();
        id = searchParams.get('id');
        console.log('xxxxxxxxxxxxxxxxx');
        console.log(searchParams);
        console.log(id);
        console.log('xxxxxxxxxxxxxxxxx');

        return <input placeholder="Search..." />
    }

    console.log('2');
    const adUlid = id;
    console.log(adUlid);

    useEffect(() => {
        const client = new Client();

        // Get the ad by the ulid
        console.log('--------------- useffect');
        console.log(adUlid);
        console.log('/--------------- useffect');

        if (adUlid) {
            client.adsGET2(adUlid)
                .then(response => {
                    console.log('--------------- response');
                    console.log(response);
                    setAd(response.ads[0]);
                    console.log('/--------------- response');
                })
                .catch(err => {
                    switch (err.status) {
                        case 400:
                            setError("Bad Request");
                            break;
                        case 401:
                            setError("Unauthorized");
                            break;
                        case 403:
                            setError("Forbidden");
                            break;
                        case 404:
                            setError("Not Found");
                            break;
                        case 500:
                            setError("Internal Server Error");
                            break;
                        default:
                            setError("Failed to fetch ads");
                    }
                    console.error("Error fetching ad:", err);
                });
        }
        else {

            //router.push('/ads/list.html');
            return;
        }
    }, [adUlid, router]);

    return (
        <Suspense>
            <div>
                {error && <p>{error}</p>}
                <ul>
                    {ad && AdElement(ad)}
                </ul>
            </div>
            <Search />
        </Suspense>
    );
}

export default withAuth(GetAd);

Solution

  • You're getting the id value in a component called Search, and not using it. And you're trying to use the id value in a component called GetAd without getting the value first.

    Why mix up the two?

    If GetAd needs to use the search params, call useSearchParams in GetAd. For example:

    const searchParams = useSearchParams();
    const adUlid = searchParams.get('id');
    
    useEffect(() => {
      // The adUlid value should be available here
    }, [adUlid, router]);
    

    You might also consider moving the Search component outside of the GetAd component to avoid further confusion.