skip to Main Content

I’m using a dockerized react+express+nginx stack. For some reason, I can only use hooks inside a few Route components from react-router-dom v6. Example:

App.jsx

 <div className="App">

      <Routes location={state?.backgroundLocation || location} >
        <Route path="/" element={<Layout />} >
          <Route index element={<TitleScreen />} />
          <Route path="/salas/" element={<RoomsScreen />} />        // INVALID HOOK CALL
          <Route path="/como-jogar" element={<h1>Como Jogar</h1>} />
          <Route path="/sala/:id" element={<RoomScreen />} />       // HOOKS WORK HERE
          <Route path="*" element={<h1>404</h1>} />
        </Route>
      </Routes>
      ...

I’m trying to make hooks work inside this function
RoomsScreen.jsx

function RoomsScreen() {
    const { rooms, loading, error, fetchRooms } = useGetRooms();

    const handleRefresh = () => {
        //should refresh RoomList
    }

    return (
        <>
            <Header title="Salas" visible={true} handleRefresh={handleRefresh} />
            <RoomList rooms={rooms} loading={loading} />
            <div className="flex-row m-1">
                <LinkButton text="Criar Sala" to="/criar-sala" useBackground={true} />
            </div>

        </>
    )
}

This is the custom hook in question
useGetRooms.jsx

const useGetRooms = () => {
    const [rooms, setRooms] = useState([]);       // THIS IS THE INVALID HOOK
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    const fetchRooms = async () => {
        try {
            const response = await getRequestWithFetch("/api/room");
            setRooms(response.rooms);
        } catch (err) {
            setError(err);
        } finally {
            setLoading(false);
        }
    };

    return { rooms, loading, error, fetchRooms };
};

What am I doing wrong?

What I tried…

I checked package.json and installs are fine.
I tried using functional components.
I also tried moving blocks of code around and playing with where in the tree I should call the hook.
If I call it inside RoomList (child of RoomScreen) it works, but I need it to be more top level.

2

Answers


  1. Chosen as BEST ANSWER

    Took me too long to solve it and the answer was unexpectedly simple... I was importing a remnant constants.jsx file with a wrong route tree for when I was setting up react-router-dom in my entry-point file. I since moved that logic to what you see in App.jsx. The error was not even visible in the question in the first place and I'm sorry for asking without looking hard enough.

    Always check your entry-point file even if it's auto generated for you!


  2. I did make an example of your custom hook with json placeholder api like this:

    useGetRooms.js

    import { useState } from "react";
    
    export const useGetRooms = () => {
      const [rooms, setRooms] = useState([]);
      const [loading, setLoading] = useState(false);
      const [error, setError] = useState(null);
    
      const getRequestWithFetch = async (url) => {
        setLoading(true);
        return await fetch(url)
          .then((res) => res.json())
          .then((data) => data);
      };
    
      const fetchRooms = async () => {
        try {
          const response = await getRequestWithFetch(
            "https://jsonplaceholder.typicode.com/todos"
          );
          setRooms(response);
        } catch (err) {
          setError(err);
        } finally {
          setLoading(false);
        }
      };
    
      return { rooms, loading, error, fetchRooms };
    };
    

    App.js

    const { error, fetchRooms, loading, rooms } = useGetRooms();
    
    <div>
     {rooms.map((each) => (
       <div>{JSON.stringify(each)}</div>
     ))}
    </div>
    <button onClick={fetchRooms}>{loading ? "Loading" : "Click"}</button>
    

    And there were no errors so you need to make sure the api you are calling is returning the data you need. There won’t be a problem calling your custom hook anywhere in react routes.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search