'How to call useSWR after getting dynamic query params in nextjs?

I'm new to NextJS. I'm having trouble understanding how useSWR hook works.

I have a dynamic URL like this - /compare/:id

Example: /compare/ferrari-vs-bmw

I need to check whether the router has returned id and then split the car brands and make multiple API requests for each brand info.

Here is what I tried:

useEffect(()=>{
    if(!router.isReady) return;

    let queryParam =  router.query.id

    let brandsList = queryParam.toString().split("-vs-")

    console.log('brandsList', brandsList);

    getData(brandsList)

    }, [router.isReady]);

    const getData = (brandsList) => {

        console.log("Geet Data>>>", brandsList);    

        for (const iterator of brandsList) {
         
            const { data, error } = useSWR(`https://api.cars/${iterator}`, fetcher)

            console.log("Data>>>", data);    
            console.log("error>>>", error);    

        }
   
    };

I got the below error

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

What's the right way to make API requests after the query param is returned in NextJS?



Solution 1:[1]

You're not allowed to call useSWR inside of a function that's not a function component. instead, just fetch the data programmatically and then use setState (setCar1 and setCar2) to store the data.

Example:

const [car1, setCar1] = useState({})
const [car2, setCar2] = useState({})
useEffect(()=>{
    if(!router.isReady) return;

    let queryParam =  router.query.id

    let brandsList = queryParam.toString().split("-vs-")

    console.log('brandsList', brandsList);

    getData(brandsList)

    }, [router.isReady]);

    const getData = (brandsList) => {

        console.log("Geet Data>>>", brandsList);    

        brandsList.forEach((brand, i) => {
         
            fetcher(`https://api.cars/${iterator}`).then((data) => {
                // If you've already called data.json() in your fetcher:
                if (i === 0) {
                    setCar1(data)
                } else {
                    setCar2(data)
                }
            })

            console.log("Data>>>", data);     
        }).catch((error) => console.log("Error>>>", error))
   
    };
});

Or something like that.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ztcollazo