Invalid hook call. Hooks can only be called inside of the body of a function component when i call useQuery in useEffect
Asked Answered
P

2

8

I am using apollo-graphql in my react project and i am getting error of

Invalid hook call. Hooks can only be called inside of the body of a function component

Here is my code for this

import React, { useEffect, useState, useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";

// **************** COMPONENTS ****************
import { GET_MORTGAGE_JOURNEY } from "../../../../Graphql/Journeys/query";

export default function index() {
  const insuranceId = useSelector((state) => state.mortgage.insuranceId);

  // Panels Heading to show on all panels

  useEffect(() => {
    if (insuranceId) {
      getMortgageData(insuranceId);
    }
  }, [insuranceId]);

  function getMortgageData(insuranceId) {
    const { loading, error, data } = useQuery(GET_MORTGAGE_JOURNEY, {
      variables: { id: insuranceId },
    });
    console.log(data);
  }

  return <section className="mortage-journey"></section>;
}

Once i run this i get the error, I know that useQuery itself is a hook and i cant call it from inside useEffect, but then what should be the workaround for this as i need insuranceId from my redux state first and send it to the query.

Thanks !

Permeance answered 26/7, 2021 at 5:37 Comment(4)
This is a function function getMortgageData(insuranceId) . You cannot call hook inside it. Neither can you call a hook from inside useEffect, since that itself is a callback function. What do you want to achieve.Aliform
initially "insuranceId" variable is null/undefined i want to pick a state from my reducer , set it to "inusranceId" and then call apollo-queryPermeance
@TusharShahi so basicallly calling GET_DATA query on mount with "insuranceId" to get my dataPermeance
Sure, I think my answer will help you. Have a look and let me knowAliform
A
0

You are breaking the rule of hooks when you call it from any place other than the top level of a React component.

useEffect takes a callback function, and you are calling your hook from that. It is a problem.

I found this skip option in useQuery which helps you call useQuery conditionally.

    const { loading, error, data } = 
    useQuery(GET_MORTGAGE_JOURNEY, {
      variables: { id: insuranceId },
      skip : (!insuranceId)
    });

Any time insuranceId changes your callback runs, so it is run after mount once and then on subsequent changes.

Aliform answered 26/7, 2021 at 6:1 Comment(2)
I tried this (for a similar issue), but it gave this error: React Hook "useMutation" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooksBrothers
this isn't the right answer and this is not the valid implementation it will through the same error again.Whereinto
A
1

Try using refetch. Something like this:

const { data, refetch } = useQuery(MY_QUERY);

useEffect(() => {
  refetch();
}, id);

You can use refetch wherever you like, in useEffect or a button click onclick handler.

Alternatively, you could use useLazyQuery if you don't want it to run the first time:

const [goFetch, { data }] = useLazyQuery(MY_QUERY);

Now you can use goFetch or whatever you want to call it wherever you like.

Your whole example might look like:

import React, { useEffect, useState, useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import { GET_MORTGAGE_JOURNEY } from "../../../../Graphql/Journeys/query";

export default function index() {
  const insuranceId = useSelector((state) => state.mortgage.insuranceId);
  const { loading, error, data, refetch } = useQuery(GET_MORTGAGE_JOURNEY, {
    variables: { id: insuranceId },
  });

  useEffect(() => {
    if (insuranceId) {
      refetch({id: insuranceId});
    }
  }, [insuranceId]);


  return <section className="mortage-journey"></section>;
}
Abbevillian answered 22/7, 2022 at 12:57 Comment(0)
A
0

You are breaking the rule of hooks when you call it from any place other than the top level of a React component.

useEffect takes a callback function, and you are calling your hook from that. It is a problem.

I found this skip option in useQuery which helps you call useQuery conditionally.

    const { loading, error, data } = 
    useQuery(GET_MORTGAGE_JOURNEY, {
      variables: { id: insuranceId },
      skip : (!insuranceId)
    });

Any time insuranceId changes your callback runs, so it is run after mount once and then on subsequent changes.

Aliform answered 26/7, 2021 at 6:1 Comment(2)
I tried this (for a similar issue), but it gave this error: React Hook "useMutation" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooksBrothers
this isn't the right answer and this is not the valid implementation it will through the same error again.Whereinto

© 2022 - 2024 — McMap. All rights reserved.