2

I am trying to use react-query with nextjs to prefetch query on server. It works for the initial query which gets a list of items. However when I try to fetch each item inside component it only fetches it on the client side.

export default function Home() {
  const { data } = useQuery("pokemons", fetchPokemons);
  return (
    <>
      <div>
        {data.map((pokemon) => (
          <Pokemon key={pokemon.name} pokemon={pokemon}/>
        ))}
      </div>
    </>
  );
}

export async function getStaticProps() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery('pokemons', fetchPokemons)
  const fetchedPokemons = queryClient.getQueryData()
  //query each pokemon
  fetchedPokemons.forEach(async (pokemon) => {
    await queryClient.prefetchQuery(pokemon.name, () => fetchPokemon(pokemon.url))
  });

  return {
    props: {
      dehydratedState: dehydrate(queryClient),
    },
  }
}

And here is code for the component which also queries each item.

const Pokemon = ({pokemon}) => {
  
  const {data} = useQuery(pokemon.name, () => fetchPokemon(pokemon.url))
  // logs only in browser, on server it is undefined
  {console.log(data)}
  return (
    <div>
      <h3>
        Name - {data.name}
        </h3>
        <h4>Base XP - {data.base_experience}</h4>
    </div>
  )
}

Can you please tell me what am I doing wrong that the query doesn't execute on server or is it an issue of the library itself?

2 Answers 2

3

when you use getQueryData to get data from the cache, you need to provide the key of the data you want to get:

await queryClient.prefetchQuery('pokemons', fetchPokemons)
const fetchedPokemons = queryClient.getQueryData('pokemons')

alternatively, you can use fetchQuery to also retrieve the data immediately

try {
  const fetchedPokemons = await queryClient.fetchQuery('pokemons')
} catch (error) {
  // handle error
}

Be aware that fetchQuery throws errors (as opposed to prefetchQuery, which does not), so you might want to handle errors somehow.

Sign up to request clarification or add additional context in comments.

Comments

0

I was able to solve this by combining two of my fetching functions into one like so

const fetchPokemons = async () => {
  const { data } = await axios.get(
    "https://pokeapi.co/api/v2/pokemon?limit=10&offset=0"
  );

  const pokemonArray = await Promise.all(
    data.results.map(async (pokemon) => {
      const res = await axios.get(pokemon.url);
      return res.data;
    })
  );

  return pokemonArray;
};

export default function Home() {
  const { data } = useQuery("pokemons", fetchPokemons);
  return (
    <>
      <div>
        {data.map((pokemon) => (
          <Pokemon key={pokemon.name} pokemon={pokemon}/>
        ))}
      </div>
    </>
  );
}

export async function getStaticProps() {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery("pokemons", fetchPokemons);

  return {
    props: {
      dehydratedState: dehydrate(queryClient),
    },
  };
}

2 Comments

Whats the reason to return "props: dehydratedState", as I don't see you using it in Home component?
getStaticProps is meant for SSG, not SSR

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.