apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

Invalid hook call when used inside React Native

Open Cretezy opened this issue 3 years ago • 7 comments

Feels like I'm going crazy about this issue. I'm currently using @apollo/client with react-native in a yarn workspace. I've setup the yarn workspace correctly with the custom metro config required, and the nohoist options. Here are my configs:

 "workspaces": {
    "nohoist": [
      "@react-native-community/async-storage",
      "react-native",
      "react-native/**",
      "react-native-dev-menu",
      "react-native-svg",
      "jetifier",
      "react-native-gesture-handler",
      "@apollo/client",
      "react"
    ]
  },
  "resolutions": {
    "@types/react": "^17",
    "react": "17.0.2",
    "@apollo/client": "3.3.21"
  },
  "dependencies": {
    "react": "17.0.2",
    "@apollo/client": "3.3.21"
    // ...
  }
const getWorkspaces = require("get-yarn-workspaces");
const path = require("path");

function getConfig(appDir) {
  const workspaces = getWorkspaces(appDir);

  const watchFolders = [
    ...workspaces.filter((workspaceDir) => !(workspaceDir === appDir)),
    path.resolve(appDir, "node_modules"),
    path.resolve(appDir, "..", "node_modules"),
  ];

  return {
    watchFolders,
    resolver: {
      extraNodeModules: {
        "react-native": path.resolve(appDir, "node_modules", "react-native"),
        react: path.resolve(appDir, "node_modules", "react"),
        "react-native-svg": path.resolve(appDir, "node_modules", "react-native-svg"),
        "core-js": path.resolve(appDir, "node_modules", "core-js"),
        "@apollo/client": path.resolve(appDir, "node_modules", "@apollo", "client"),
      },
    },
  };
}

module.exports = getConfig(__dirname);

This works as expected, and normal React hooks works. But using useQuery gives me:

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://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

This error is located at:
    in AppInner (at App.tsx:44)
    in ApolloProvider (at App.tsx:43)
    in App (at renderApplication.js:47)
    ...

My application code is:

import { AppRegistry } from "react-native";
import { App } from "./src/components/App";
import { name as appName } from "./app.json";
import "react-native-gesture-handler";

AppRegistry.registerComponent(appName, () => App);
import React, { useCallback, useContext, useEffect } from "react";
import { Text } from "react-native";
import {
  ApolloClient,
  ApolloProvider,
  useQuery,
} from "@apollo/client";
import { useQueryHookFromOtherPackage } "@propty/code/src/generated"

const client = new ApolloClient({
  // ...
});

export const App: React.FC = () => {
  return (
    <ApolloProvider client={client}>
      <AppInner />
    </ApolloProvider>
  );
};

const AppInner: React.FC = () => {
  // This hook is generated using GraphQL code generation in a package inside our yarn workspace
  useQueryHookFromOtherPackage()

  return <Text>test</Text>

It seems like it's specifically the useQuery hook that breaks, as other hooks there works fine.

I've checked and @apollo/client and react are also properly hoisted, meaning they should not be any weird version issues.

Cretezy avatar Jul 22 '21 15:07 Cretezy

@Cretezy Can you run npm ls react react-dom and share the output?

Alternatively/additionally, Apollo Client v3.4 is very close to release, and some aspects of importing/exporting React stuff have changed internally, so there's always a chance updating with

npm i @apollo/client@beta

could solve some problems.

benjamn avatar Jul 22 '21 19:07 benjamn

@benjamn

➜  yarn why react           
yarn why v1.22.10
[1/4] Why do we have the module "react"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
[4/4] Calculating file sizes...
=> Found "[email protected]"
info Reasons this module exists
   - "_project_#@propty#frontends-mobile" depends on it
   - Hoisted from "_project_#@propty#frontends-mobile#react"
   - Hoisted from "_project_#@propty#frontends-web#react"
   - Hoisted from "_project_#@propty#frontends-storybook#react"
info Disk size without dependencies: "356KB"
info Disk size with unique dependencies: "404KB"
info Disk size with transitive dependencies: "432KB"
info Number of shared dependencies: 3
Done in 0.98s.


➜   yarn why react-dom      
yarn why v1.22.10
[1/4] Why do we have the module "react-dom"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
[4/4] Calculating file sizes...
=> Found "[email protected]"
info Reasons this module exists
   - "_project_#@propty#frontends-web" depends on it
   - Hoisted from "_project_#@propty#frontends-web#react-dom"
   - Hoisted from "_project_#@propty#frontends-storybook#react-dom"
info Disk size without dependencies: "2.93MB"
info Disk size with unique dependencies: "3.18MB"
info Disk size with transitive dependencies: "3.21MB"
info Number of shared dependencies: 4
Done in 0.72s.


➜   npm ls react react-dom
@propty/[email protected] /.../frontends/mobile
└── (empty)

Cretezy avatar Jul 22 '21 19:07 Cretezy

@benjamn No luck with @apollo/[email protected] either

Cretezy avatar Jul 22 '21 19:07 Cretezy

Okay narrowed it down a little.

My original code of using the following works:

useQuery(gql`
    query {
      me {
        id
      }
    }
  `);

However, using a generated hook from the GraphQL code gen, imported from a package in the workspace, does not. We have a package (@propty/core) in the workspace where the .graphql files are, and where the code gen happens. We import this package on our web/mobile packages. I've updated the OP with the "real" example (importing a generated hook)

I've tried unhoisting @apollo/client with no success.

Any ideas?

Cretezy avatar Jul 22 '21 20:07 Cretezy

having the same issue

batical avatar Jul 23 '21 10:07 batical

I've found the source of the problem.

My current yarn workspace looks like:

  • /: The root
    • core: Where the Apollo Hooks are generated
    • mobile: The React Native applications that's problematic
    • web

Inside mobile/package.json, I have:

 "workspaces": {
    "nohoist": [
      "**/*"
    ]
  },

And in /package.json, I have:

  "workspaces": {
    "packages": [
      "web",
      "mobile",
      "core"
    ],
    "nohoist": [
      "**/react",
      "**/react/**",
      "**/@apollo/client",
      "**/@apollo/client/**"
    ]
  },

The problem

My core package has @apollo/client as a devDependency (mobile also has it). When I remove @apollo/client from the core's devDependency, I can use the hooks correctly.

This doesn't seem to be strictly a problem with @apollo/client, but more of a Metro/React Native issue.

No matter what I do, as long as @apollo/client is in the devDependencies, this error appears.

Cretezy avatar Jul 25 '21 23:07 Cretezy

Currently using @apollo/[email protected]. Still getting the same error as OP.

mangkoran avatar Jan 17 '22 13:01 mangkoran