Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Invalid hook call when calling a function

I’m doing a React project. I have two reutilizable functions that made requests to an API. When I call the functions, react raise the 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

I have fetchCustomers.jsx:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

export default function fetchCustomers() {
  const [customers, setCustomers] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('customers/', {
          headers: {
            'Authorization': `Bearer ${localStorage.getItem('access_token')}`
          }
        });
        setCustomers(response.data);
      } catch (error) {
        console.error("Error al obtener los datos de clientes.", error);
      }
    };

    fetchData();
  }, []);

  return customers;
}

fetchSales.jsx:

export default function fetchSales(params = {}) {
  const [sales, setSales] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('sales/', {
          params: params,
          headers: {
            'Authorization': `Bearer ${localStorage.getItem('access_token')}`
          }
        });
        setSales(response.data.results);
      } catch (error) {
        console.error("Error al obtener los datos de ventas.", error);
      }
    };

    fetchData();
  }, []);

  return sales;
}

and cobrar.jsx:

export default function Cobrar() {
  const [filter, setFilter] = useState({
    startDate: null,
    endDate: null,
    customer: null,
    uncharged: true,
  });
  const [customers, setCustomers] = useState([]);
  const [sales, setSales] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const customersResponse = fetchCustomers();
        setCustomers(customersResponse);
        const salesResponse = fetchSales();
        setSales(salesResponse);
      } catch (error) {
        console.error("Error al obtener los datos.", error);
      }
    }

    fetchData();
  }, []);

I tried call the functions in the const and works but I can’t filter the sales by params. I want to get all the sales and then filter by daterange and some fields.

>Solution :

fetchCustomers and fetchSales are written as hooks, not as otherwise regular functions. First, rename them to useCustomers and useSales (to be consistent with the naming for hooks). Then, use them as hooks in your component:

export default function Cobrar() {
  const [filter, setFilter] = useState({
    startDate: null,
    endDate: null,
    customer: null,
    uncharged: true,
  });

  const customers = useCustomers();
  const sales = useSales();

  // the rest of this component...

You don’t need to repeat the usage of state because the hooks internally maintain their state.


Alternatively, if you don’t want these functions to be custom hooks, remove their internal use of hooks and just make them functions that return results directly. For example:

export default async function fetchCustomers() {

  const response = await axios.get('customers/', {
    headers: {
      'Authorization': `Bearer ${localStorage.getItem('access_token')}`
    }
  });

  return response.data;

}

Then you can call the function in any context without an invalid hook call, since the function no longer tries to use hooks.


Overall:

  • Don’t double-up on tracking data in state. Keeping multiple data sources synchronized is a hard problem to solve, and an unnecessary one. Track the state in the component or in a hook, not both.
  • Hooks can only be called from components or other hooks, and must always be called in the same order when rendering the component/hook. They can’t be called conditionally, within functions, etc.
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading