Intended outcome:
Work without errors.
Actual outcome:
Uncaught Invariant Violation: 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
How to reproduce the issue:
I have an Electron + typescript app that just renders one component.
import React from 'react'
import { render } from 'react-dom'
import { ApolloProvider } from 'react-apollo'
const Test = () => {
const { data } = useQuery(GET_USERS)
console.log(data)
return null
}
render(
<ApolloProvider client={client}>
<Test />
</ApolloProvider>,
document.getElementById('app')
)
Version
"react-apollo": "3.0.1",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"apollo-client": "^2.6.3",
@osenvosem Have you double checked You might have more than one copy of React in the same app? This is usually the culprit, especially when integrating with projects like React Native; something similar might be happening with Electron. If you still think this is a React Apollo issue though, please provide a small runnable reproduction and we'll take a look. Thanks!
@hwillson npm ls react shows only one instance of react. React hooks work well, the issue arises only with apollo-client hooks. I'm not sure why this issue is closed.
+1 Same behavior with import { useQuery } from '@apollo/react-hooks'
I've just started seeing the same thing after upgrading to expo sdk35 (React 16.8.3) :(
Interestingly useRef works without any issues just one line above the useQuery call
I have a freshly installed project with create-react-app and see this problem too.
In our case the issue was due to our umbrella app containing different react versions and I couldn't figure out how to get everything to use the right react versions. In the end we pinned all react versions to the one required by the react native app.
Hi @tonnenpinguin can you post working package.json please?
@Kif11 it pretty much boils down to setting a specific version for react
"react": "16.8.3",
+1 for this, I'm having the same issue as well ( minimal example project ):
import React from "react";
import ReactDOM from "react-dom";
import {ApolloProvider, useQuery} from "@apollo/react-hooks";
import gql from "graphql-tag";
import {InMemoryCache} from "apollo-cache-inmemory";
import {HttpLink} from "apollo-link-http";
import {ApolloClient} from "apollo-client";
const cache = new InMemoryCache();
const link = new HttpLink({
uri: 'http://localhost:9001/'
});
const client = new ApolloClient({
cache,
link
});
const GET_USERS = gql`
query GetUsers {
getUsers {
id
}
}
`;
const Test = () => {
const {data} = useQuery(GET_USERS);
console.log(data);
return null
};
ReactDOM.render(<ApolloProvider client={client}><Test/></ApolloProvider>, document.getElementById("app"));
Gets the error:
Uncaught 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
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
at resolveDispatcher (:9080/Users/mwingfield/Documents/drapery_software/client/electron/node_modules/react/cjs/react.development.js:1590)
at useContext (:9080/Users/mwingfield/Documents/drapery_software/client/electron/node_modules/react/cjs/react.development.js:1598)
at useBaseQuery (:9080/Users/mwingfield/Documents/drapery_software/client/electron/node_modules/@apollo/react-hooks/lib/react-hooks.cjs.js:474)
at useQuery (:9080/Users/mwingfield/Documents/drapery_software/client/electron/node_modules/@apollo/react-hooks/lib/react-hooks.cjs.js:526)
at Test (webpack-internal:///./src/renderer/index.tsx:56)
at renderWithHooks (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:16241)
at mountIndeterminateComponent (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:18775)
at beginWork$1 (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:20137)
at HTMLUnknownElement.callCallback (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:336)
at Object.invokeGuardedCallbackDev (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:385)
webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:21810
```
The above error occurred in the
in Test
in ApolloProvider
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
Here is my `package.json`
```json
{
"name": "testname",
"productName": "testname",
"version": "0.0.12",
"scripts": {
"dev": "electron-webpack dev",
"compile": "electron-webpack"
},
"build": {
"appId": "com.testname.testname",
"productName": "testname",
"copyright": "Copyright © 2019 testname",
"publish": {
"provider": "s3",
"bucket": "testname"
},
"win": {
"target": "nsis"
},
"mac": {}
},
"dependencies": {
"@apollo/react-components": "^3.1.3",
"@apollo/react-hoc": "^3.1.3",
"@apollo/react-hooks": "^3.1.3",
"@reach/router": "^1.2.1",
"apollo-cache": "^1.3.2",
"apollo-cache-inmemory": "^1.6.2",
"apollo-client": "^2.6.3",
"apollo-link": "^1.2.13",
"apollo-link-http": "^1.5.15",
"apollo-utilities": "^1.3.2",
"electron-log": "^3.0.8",
"electron-updater": "^4.1.2",
"graphql": "^14.4.2",
"graphql-tag": "^2.10.1",
"react": "16.11.0",
"react-dom": "16.11.0",
"react-scripts": "^3.2.0",
"source-map-support": "^0.5.16",
"spectre.css": "^0.5.8"
},
"devDependencies": {
"@babel/cli": "^7.6.4",
"@babel/core": "^7.6.4",
"@babel/preset-env": "^7.6.3",
"@babel/preset-react": "^7.6.3",
"@graphql-codegen/cli": "^1.8.2",
"@graphql-codegen/introspection": "1.8.2",
"@graphql-codegen/typescript": "1.8.2",
"@graphql-codegen/typescript-operations": "^1.8.2",
"@graphql-codegen/typescript-react-apollo": "1.8.2",
"@types/reach__router": "^1.2.6",
"@types/react": "^16.9.11",
"@types/react-dom": "^16.9.3",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.6",
"babel-preset-es2015-node": "^6.1.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^3.2.0",
"electron": "5.0.6",
"electron-builder": "^21.0.11",
"electron-webpack": "^2.7.4",
"eslint": "^6.6.0",
"eslint-plugin-react-hooks": "^2.2.0",
"standard": "^14.3.1",
"standard-loader": "^7.0.0",
"style-loader": "^1.0.0",
"ts-loader": "^6.2.1",
"tslint": "^5.20.0",
"tslint-config-standard": "^8.0.1",
"tslint-loader": "^3.5.4",
"typescript": "^3.6.4",
"webpack": "^4.41.2",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.9.0"
}
}
After some testing, I've narrowed it down to a single variable:
package.json
{...
"dependencies":{...
"react-apollo": "^2.5.8",
...}
...}
works as expected.
package.json
{...
"dependencies":{...
"react-apollo": "^3.0.0",
...}
...}
Fails with the Invalid Hooks error.
@hwillson thoughts?
I am having the same issue inside yarn workspaces/lerna where all the apollo logic is within a controllers package. I rewrote the package to only use @apollo/[email protected] which works perfectly fine inside the web app. Using the exact same package inside the native app gives the hook error.
I tried running the native app detached from lerna/workspaces but still have the error. I also use the exact same code and versions to create the client/provider.
yarn list --pattern react also doesn't show any duplicated versions of react. Also all the react versions are hard set + set in the resolutions field in the root package.
Regular react hooks seem to work fine in the native app, using hooks directly without my own controllers also gives the error.
@Kenoshen @hwillson Did you guys find a solution?
@klaaz0r I'm using "react-apollo": "^3.0.1" with Yarn Workspaces in a react-native project, and I was able to fix this just by installing @apollo/react-hooks.
One thing I might be doing different from you is using the nohoist Workspace option (https://yarnpkg.com/blog/2018/02/15/nohoist/)
If you haven't tried it, this option allows you to prevent dependencies from being shared across workspaces. In my case, I chose to just completely disable the hoisting feature using this in my root package.json:
{
"workspaces": {
"packages": [
"projects/*"
],
"nohoist": [
"**"
]
},
}
Issue still exists.
import React, { useState } from 'react';
import {
FormGroup,
Label,
Input,
Container,
Button,
} from 'reactstrap';
import { useQuery } from '@apollo/react-hooks';
import {
ADD_USER,
} from '../Queries';
const Userform = (prop) => {
const [user, setUser] = useState({
name: '',
email: '',
job_title: ''
});
const updateUser = (e) => {
setUser({
...user,
[e.target.id]: e.target.value
});
}
const SaveUser = () => {
let result = useQuery(ADD_USER, {
variables: {
...user
}
});
};
return (
<Container>
<FormGroup>
<Label for="name">Name: </Label>
<Input type="text" id="name" onChange={updateUser} />
</FormGroup> <br/>
<FormGroup>
<Label for="email">E-mail: </Label>
<Input type="email" id="email" onChange={updateUser} />
</FormGroup> <br/>
<FormGroup>
<Label for="job-title">Job Title: </Label>
<Input type="text" id="job_title" onChange={updateUser} />
</FormGroup>
<Button onClick={SaveUser}>Save</Button>
</Container>
);
}
export default Userform;
it errors on the useQuery.
with the version
"@apollo/react-hooks": "^3.1.3",
"apollo-boost": "^0.4.4",
"graphql": "^14.5.8",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.2.0",
I got same issue too with both useQuery and useMutation
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
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
If this helps anyone I was working with Gatsby and had the same error, but looking in the documentation found this:
Your app is not correctly hydrated, which results in gatsby develop and gatsby build being inconsistent. It’s possible that a change in a file like gatsby-ssr or gatsby-browser has a structure that is not reflected in the other file, meaning that there is a mismatch between client and server output.
I had different output in the gatsby-browser and gatsby-ssr files. I just had to ensure that those files export a similar structure and that solved this error.
same issue...please help...
Action
import React from "react";
import * as ACTION_TYPES from "./../constants/action-types";
import { useQuery } from "@apollo/react-hooks";
import gql from 'graphql-tag';
export const getCharactersSuccess = (data) => {
return {
type:ACTION_TYPES.LOAD_CHARACTERS_SUCCESS,
data
}
}
export const getCharactersInProgress = () => {
return {
type:ACTION_TYPES.LOAD_CHARACTERS_INPROGRESS
}
}
export const getCharactersError = (error) => {
return {
type:ACTION_TYPES.LOAD_CHARACTERS_ERROR,
error
}
}
const GET_CHARACTERS =gql`
{
allPersons {
name
gender
homeworld {
name
}
species {
name
language
classification
}
}
}`;
export const useGetCharacters= () => {
const { loading, error, data } = useQuery(GET_CHARACTERS);
if(loading) {
getCharactersInProgress();
}
if(error) {
getCharactersError(error);
}
if(data) {
getCharactersSuccess(data);
}
}
Reducer
export const ContextState = (props) => {
// const [stateReducer, dispatchReducer] = useReduceWithLogger(Reducer.AppLoadingReducer,Reducer.initialState);
const [stateReducer, dispatchReducer] = useReducer(Reducer.MainReducer,Reducer.initialState);
const handleDispatchAppLoadingInProgress = () => {
dispatchReducer(GENERIC_ACTION.appLoadingInprogress());
}
const handleDispatchAppLoadingSuccess = () => {
dispatchReducer(GENERIC_ACTION.appLoadingSuccess());
}
// const getCharacters = () => {
// dispatchReducer(GET_CHARACTERS_ACTION.useGetCharacters());
// }
const graphqlClient = new ApolloClient({
uri: "https://swapi.graph.cool/"
});
return (
<div>
<ApolloProvider client={graphqlClient}>
<Context.Provider
value={{
// reducer
isAppReady: stateReducer.isAppReady,
dispatchAppLoading: () => handleDispatchAppLoadingInProgress(),
dispatchAppLoaded: () => handleDispatchAppLoadingSuccess(),
// get character action
getCharacters: () => dispatchReducer(GET_CHARACTERS_ACTION.useGetCharacters())
}}
>
{
props.children
}
</Context.Provider>
</ApolloProvider>
</div>
)
}
Same problem here.
I checked the react version etc. useState does work useSubscriptions gives the following error.
Uncaught 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:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app
Why is this closed?
Running into this same issue, some solution/guidance would be appreciated
Same here. lerna + yarn workspaces + react-apollo
Ends up with an error though, no warnings
TypeError: this.currentObservable.query.getCurrentResult is not a function :
QueryData.getQueryResult
C:/temp/cra-workspaces-playground/packages/apps/src/data/QueryData.ts:337
334 | };
335 | } else {
336 | // Fetch the current result (if any) from the store.
> 337 | const currentResult = this.currentObservable.query!.getCurrentResult();
| ^ 338 | const { loading, partial, networkStatus, errors } = currentResult;
339 | let { error, data } = currentResult;
340 |
Same issue.
render() {
const { loading, error, data } = useQuery(Graphs.LIST_DEVICES);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
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
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
â–¶ 5 stack frames were collapsed.
ClientView.render
src/components/Body/ClientView/ClientView.jsx:21
18 | // return <div>{props.name} {props.phone}</div>;
19 | // }
20 |
> 21 | render() {
| ^ 22 | const { loading, error, data } = useQuery(Graphs.LIST_DEVICES);
23 | if (loading) return <p>Loading...</p>;
24 | if (error) return <p>Error :(</p>;
@isaiahtaylor @sebastienfi @Knaackee try to install @apollo/react-hooks to package not in the root
I have the same problem with monorepo
@isaiahtaylor You are "breaking the Rules of Hooks". https://reactjs.org/docs/hooks-rules.html#only-call-hooks-from-react-functions
You shouldn't be using hooks inside a render function. You should convert your Component to a Function Component.
@sebastienfi To go along with what @Whispers12 said, the nohoist option is likely what you need if you are using Yarn Workspaces. (https://github.com/apollographql/react-apollo/issues/3454#issuecomment-554387817)
@Whispers12 already tried that with no success
@traviswimer i am using a functional component
@traviswimer I don't use yarn workspaces. I have all my modules in my package.json of my project
@isaiahtaylor You are "breaking the Rules of Hooks". https://reactjs.org/docs/hooks-rules.html#only-call-hooks-from-react-functions
@traviswimer you are correct! That was my issue. Thank you.
@Knaackee My comment wasn't directed at you, but to answer your original question, I think this was closed because its more likely to be a react issue like the error suggests.
I don't really know what to suggest other than the normal silly node fixes like deleting node_modules, upgrading your react dependencies, etc.
You might have better luck if you can post a question with some code on Stackoverflow.
Still having this issue
Some solution? I have same issue in monorepo with react native. React hooks work fine like useEffect or useState
I also have the same problem with monorepo and react native..
I even tried to create a clean application with only the bare minimum and it doesn't work.. why is this issue closed?
I fixed it,
Apparently it seems like it is related to two react versions (even though i had only one).
To solve it I had to specifically tell metro bundler from where to resolve react using babel-plugin-module-resolver:
yarn workspace @your/workspace add --dev babel-plugin-module-resolver
in _babel.config.js_
module.exports = {
// ...
plugins: [
[
'module-resolver',
{
root: ['./mobile'],
extensions: ['*'],
alias: {
react: './node_modules/react',
},
},
],
// ...
],
};
Hey, I'm having this issue only when trying to test. I am using react-native, apollo, graphql-code-generator and typescript. I am trying to get my tests set up with jest and @testing-library/react-native. The tests work except when I try to test a file using one of the ApolloReactHooks I get this error.
Invariant Violation: 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
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
2443 | export function useDashboardQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<DashboardQuery, DashboardQueryVariables>) {
> 2444 | return ApolloReactHooks.useQuery<DashboardQuery, DashboardQueryVariables>(DashboardDocument, baseOptions);
| ^
2445 | }
2446 | export function useDashboardLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<DashboardQuery, DashboardQueryVariables>) {
2447 | return ApolloReactHooks.useLazyQuery<DashboardQuery, DashboardQueryVariables>(DashboardDocument, baseOptions);
at node_modules/react/cjs/react.development.js:1533:26
at resolveDispatcher (node_modules/react/cjs/react.development.js:1536:5)
at useContext (node_modules/react/cjs/react.development.js:1541:20)
at useBaseQuery (node_modules/@apollo/client/react/hooks/utils/useBaseQuery.js:11:19)
at Object.useQuery (node_modules/@apollo/client/react/hooks/useQuery.js:4:12)
at useDashboardQuery (App/generated/graphql.tsx:2444:33)
at Dashboard (App/screens/Dashboard/index.tsx:117:45)
at renderWithHooks (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:5762:18)
at mountIndeterminateComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7996:13)
at beginWork$1 (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9140:16)
I am calling it in a function component along side other hooks that are working just fine. I tried all the suggestions in this thread and others around getting the invalid hook error and I have run out of ideas. Again this is working when I run my dev server or a production build. It just is not working when I run tests. Any thoughts or ideas would be appreciated.
Test:
import React from 'react'
import { render } from '@testing-library/react-native'
import { MockedProvider } from '@apollo/client/testing'
import { TestComponent } from './TestComponent'
const mocks = []
function setup() {
const comp = render(
<MockedProvider mocks={mocks}>
<TestComponent testID='test' value={10} />
</MockedProvider>
)
return { ...comp }
}
describe('TestComponent', () => {
it('renders', () => {
const { getByTestId } = setup()
expect(getByTestId('test')).toBeTruthy()
})
})
Component:
import React, { useState } from 'react'
import { useDashboardQuery } from '../../generated/graphql'
import { NumProps, Num } from './Num'
type TestComponentProps = NumProps
export const TestComponent: React.FC<TestComponentProps> = ({ value, ...props }) => {
const [state, setState] = useState(true)
const { data } = useDashboardQuery({ userId: "1" })
console.log(state)
console.log(data)
return <Num value={value} {...props} />
}
babel.config.js:
module.exports = function (api) {
api.cache(true)
return {
presets: [
'babel-preset-expo',
'module:react-native-dotenv',
'module:metro-react-native-babel-preset'
],
plugins: [
[
'babel-plugin-inline-import',
{
extensions: ['.svg']
}
],
]
}
}
jest.config.js:
module.exports = {
preset: 'jest-expo',
clearMocks: true,
collectCoverage: false,
collectCoverageFrom: ['App/**/*.[tj]s'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
resetMocks: true,
resetModules: true,
rootDir: '.',
transform: {
'^.+\\.(ts)$': 'ts-jest',
'^.+\\.tsx?$': 'babel-jest',
'^.+\\.jsx?$': 'babel-jest'
},
verbose: true
}
Oh yea and my apollo version:
"dependencies": {
"@apollo/client": "^3.0.0-beta.38",
Same issue
Most helpful comment
+1 Same behavior with
import { useQuery } from '@apollo/react-hooks'