Home > Software engineering >  Why is this NextJS query string undefined on subsequent page reloads?
Why is this NextJS query string undefined on subsequent page reloads?

Time:03-19

I have a NextJS application where I am building a search results page based on a query parameter being passed. I am using the next/router to pick up the query string. The first time the page loads after compilation the querystring gets picked up and the call to the API is successful and returns results. Every subsequent try, whether on a F5 refresh, reloading the page via the reload button, or accessing the page again the call to the API gives no results because the querystring is undefined.

the URL: http://localhost:3000/search?search=blah

import { useRouter } from "next/router";
import React, { useEffect, useState } from 'react';
import axios from 'axios'

export default function SearchResults1(props) {
    const { query } = useRouter();
    const [searchResults, setSearchResults] = useState({})
    const [ getQuery, setQuery] = useState({})

    useEffect(() => {
        function fetchData(){
            setQuery(query.search)
            console.log(getQuery)
            if (getQuery) {
                axios.get(`http://localhost:3001/search/${getQuery}`)
                .then((response) => {
                    setSearchResults(response.data)
                })
                .catch((error) => {
                    console.warn(error)
                })
            }
        }
        fetchData()
    },[getQuery, setQuery])

I tried adding the getQuery and setQuery in the useEffect hook so it would be triggered when there are changes, but i still get undefined whenever i load the page a second time.

I also tried removing the getQuery and setQuery and tried without using state, but I still get the same result if I call the query.search directly - the first time it works, subsequently it does not.

I did notice that if I called {query.search} in the return HTML it always renders - so I am thinking it has something to do with perhaps the API call happening and not waiting for the query to be populated.

return (
    <div>{query.search}</div> <!--this always works and shows the correct value-->
)

Any thoughts or suggestions on how I can achieve consistent results and always return the query parameters so I can make a good API call? I'm fairly confident I am missing something obvious.

CodePudding user response:

Instead of parsing it directly with the useRouter(), try to get the router ready state and access it once it is ready in the useEffect.

import { useRouter } from "next/router";
import React, { useEffect, useState } from 'react';
import axios from 'axios'

export default function SearchResults1(props) {
    const router = useRouter();
    const [searchResults, setSearchResults] = useState({})
  //const query = router.query; <-- or use this. The point is to access router.isReady in useEffect

    useEffect(() => {
        if (!router.isReady) return; // <-- only use the query when it is ready. 
        function fetchData(){
            axios.get(`http://localhost:3001/search/${router.query.search}`)
            .then((response) => {
                setSearchResults(response.data)
            })
            .catch((error) => {
                console.warn(error)
            })
        }
        fetchData()
    },[router.isReady]) // <-- use this router.isReady

According to the Next.js, It will be an empty object during prerendering if the page doesn't have data fetching requirements.

https://nextjs.org/docs/api-reference/next/router

This way, we can make sure the router information is ready for use when you access it.

  • Related