Attempting to call a hook outside of a function component's body results in an invalid hook call. The proper usage for hooks like useQuery is within the body

I am encountering an issue with my react project that involves apollo-graphql. The error message states:

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

Below is the snippet of code triggering this error:

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>;
}

When running this code, I receive the mentioned error. I understand that useQuery is itself a hook and cannot be called within useEffect. Is there any workaround to access insuranceId from my redux state before passing it to the query?

Thank you!

Answer №1

Consider implementing the refetch function. It can be done in this manner:

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

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

The refetch method is versatile and can be used within a useEffect hook or even as part of a button click event using onclick handler.

If you prefer to avoid triggering the query on initial load, you may also utilize useLazyQuery:

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

This approach allows you to call goFetch (or any other preferred name) at your convenience.

An example implementation could resemble the following code snippet:

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>;
}

Answer №2

It's important to follow the rule of hooks by only calling them at the top level of a React component.

If you're using useEffect, make sure not to call your hook inside the callback function as it can cause issues.

Consider using the skip option in useQuery to conditionally call the hook.


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

Remember that when insuranceId changes, your callback will run - once after mount and then on subsequent changes.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Data within object not recognized by TableCell Material UI element

I am currently facing an issue where the content of an object is not being displayed within the Material UI component TableCell. Interestingly, I have used the same approach with the Title component and it shows the content without any problems. function ...

Prevent the browser from autofilling password information in a React Material UI textfield when it is in focus

I am currently utilizing React Material UI 4 and I am looking to disable the browser autofill/auto complete suggestion when focusing on my password field generated from `TextField`. Although it works for username and email, I am encountering issues with d ...

Create a JavaScript button that redirects to a different page within a React application

I am creating a div element using a for-loop and I want to link each div to the "/campaign" page with its respective id. When a div is clicked, I want it to navigate to the "/campaign/id" page and pass the id to the Campaign component. class Home extends ...

Sharing information between External JavaScript and React JS/Redux

Incorporating React-redux into an externalJs application (built on a custom JS framework) has posed a challenge for me. I am trying to initialize data for the Redux store from externalJS, but it seems that the external script is unable to access the React ...

What is the best way to use Google Material-Design-Icons in my project once I have installed it

Once I've installed the material-design-icons package using npm, how can I incorporate them into my React application? The instructions provided here do not mention the npm method. ...

axios: prevent automatic sorting of objects according to keys

When using axios, I am receiving an API response. To send the sorted API response based on name, I use the following endpoint: http://localhost:8000/api/ingredients/ordering=name The actual object received from my server looks like this: { 2:{"id":2 ...

What is the best way to retrieve the primaryText value within the onChange function of a SelectField component?

I am trying to access the primaryText from the onChange method of SelectField. However, onChange only provides (event,index,value). Here is my code snippet: <SelectField value={props.value} onChange={this.handleChange}> {props.opt ...

provide the React Context value as an argument

I'm facing an issue where I cannot pass a context value as a parameter when calling a function from another file. The code I have is shown below: import React, { useContext } from React import { AuthContext } from "src/contexts/AuthContext"; ...

When using useEffect to mimic componentWillUnmount, the updated state is not returned

My goal is to have a functional component with initialized state using useState, which can be updated through an input field. However, upon unmounting the component, I want to log the current state instead of the initial one. In this hypothetical scenario ...

React Render causing Unexpected Token Issue

Having trouble with two React Apps - one main app and the other just a simple app with 1 component. I've imported the component package as node_module using npm link. Can someone guide me on how to resolve this issue? Here is the code for the SubApp ...

How to pass only the clicked element to the onClick function in React.js

I have several elements with the same className, and I want to add the className active to an element (with the className history-node) when it is clicked, in addition to its current className. However, I am facing an issue where the child elements of tha ...

I am having difficulty accessing the dataset on my flashcard while working with React/Next JS

I'm currently developing a Flashcard app that focuses on English and Japanese vocabulary, including a simple matching game. My goal is to link the two cards using a dataset value in order to determine if they match or not. When I click on a flashcar ...

How to visually represent options without labels using icons in Material UI Autocomplete

My options are structured as follows: const options = ['option1', 'option2']; I am looking to display the options with icons like this: https://i.stack.imgur.com/aubHS.png The current code for rendering options looks like this: ...

What are some creative ways to emphasize certain dates?

Is there a way to customize mui-x-date-pickers to highlight specific days from a Date array with green filled circles around them? I am using new Date and wondering how to achieve this effect. Below is the code snippet I am currently working with: <Dat ...

Implementing a color change for icons in React upon onClick event

export default function Post({post}) { const [like,setLike] = useState(post.like) const [islike,setIslike] = useState(false) const handler=()=>{ setLike(islike? like-1:like+1 ) setIslike(!islike) } return ( <> <div classNam ...

Is there a way to perform async-await operations one after the other?

I need to save the token in a cookie and then navigate to "/". In this "/" route, it requires the token value to be present in order to work properly. So, my plan is to use setCookie to store the token and then navigate once the token is available. I hav ...

Issue: Encounter an Error with Status Code 401 using Axios in React.js

For my login page, I am utilizing a combination of Laravel API and ReactJS frontend. In my ReactJS code, I am using Axios to handle the parsing of the username (email) and password. The login API endpoint is specified as http://127.0.0.1:8000/api/login, wh ...

Error Encountered: Unhandled Runtime Error in Next.js with Firebase - TypeError: Unable to access the property 'initializeApp' as it is undefined

It's baffling why this error keeps appearing... my suspicion is directed towards this particular file. Specifically, firebaseAuth={getAuth(app)} might be the culprit. Preceding that, const app = initializeApp(firebaseConfig); is declared in "../f ...

Display the user IDs associated with each historical route

Utilizing the react-ga npm module, I successfully integrated Google Analytics into my React website. Through this implementation, I have been able to produce user reports as well as page view analytics. https://i.stack.imgur.com/CWwQE.png I specifically ...

React client side componentDidMount function encountering issues (server side rendering)

Greetings to the Stackoverflow community Apologies in advance if my explanation is not clear enough When a user directly types a URL, the server makes a request, fetches the corresponding data, and renders it on the screen flawlessly. However, when a us ...