Home > Net >  React Hooks must be called in the exact same order in every component render error when building app
React Hooks must be called in the exact same order in every component render error when building app

Time:09-17

I am building a NextJs App and everything works well in dev. However when I am trying to build the application I get the errors:

./pages/genre.js/[genre].js

15:14 Error: React Hook "useFetchTrendingCatagory" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks

17:14 Error: React Hook "useFetchTopRatedCatagory" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks

19:14 Error: React Hook "useFetchMovieGenreResults" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks

My code is below:

import React from "react";
import { useRouter } from "next/router";
import useFetchMovieGenreResults from "../../hooks/useFetchMovieGenreResults";
import { useState } from "react";
import useFetchTrendingCatagory from "../../hooks/useFetchTrendingCatagory";
import useFetchTopRatedCatagory from "../../hooks/useFetchTopRatedCatagory";

const useMovies = (genre) => {
  switch (genre) {
    case 'Trending':
      return useFetchTrendingCatagory()
    case 'Top Rated"':
      return useFetchTopRatedCatagory()
    default:
      return useFetchMovieGenreResults(genre)
  }
}

export default function Genre () {
  const router = useRouter();
  const { genre } = router.query;
  const mymovies = useMovies(genre)

  return (
    <div>
      {/* <Navbar /> */}
      <div>{genre}</div>
      <Moviegenreresults movies={mymovies} />
    </div>
  )
}

Why is this error happening and is there a work-around for this error?

CodePudding user response:

What's happening is exactly what the error says, useMovies gets a different hook based on a condition which is the name of the genre, therefor the order of your hooks may be changed according to the arguments you pass to the useMovies hook.

Instead of having a switch that is returning a different hook based on the genre you passed make all the hook logic inside of one f.e useMovies hook and everything that needs to be modified (I assume for example the endpoint or the data you pass to that endpoint) pass it as your argument and make it work there.

CodePudding user response:

Technically the error is exactly how it sounds. You can't call hooks conditionally. What you're doing in the intermediate useMovies function with the switch statement is conditionally calling a hook. You may want to make that hook just something like useFetchMovies and just pass the genre into it, then inside of the hook itself do the logic that is happening in the useMovies function. Assuming you are just fetching from different endpoints in the different hooks you could do something like this, then return the fetcher function, or even use it in an effect if you really wanted to.

const useFetchMovies = (genre = null) => {
  const [movies, setMovies] = useState([]);

  const fetchMovies = async() => {
    let url;

    switch (genre) {
      case "Trending":
        url = "whatever the url you need is for this";
      case 'Top Rated"':
        url = "whatever the url you need is for this";
      default:
        url = "whatever the url you need is for this";
    }

    try {
      const response = await fetch(url);

      console.log('response', response)

      setMovies(response);
    } catch (err) {
      console.error(err);
      throw err;
    }
  };

  return {
    movies,
    setMovies,
    fetchMovies
  };
};

  • Related