'How to use Apollo/Graphql hooks within external React.js component library
I have 3 React.js projects and I'm trying to consolidate the reused components across all 3 projects into one shared component library.
This component library is hosted on Github and imported into all 3 projects through the package.json
file like this:
"components": "github:myusername/components"`
I am then able to import the components from the library into each project like such:
import { Form } from "components"
but when the component being imported (in this case a Form
) uses an Apollo/Graphql hook (useQuery
, or useMutation
) I get this error:
Uncaught Invariant Violation: Could not find "client" in the context or passed in as an option. Wrap the root component in an <ApolloProvider>, or pass an ApolloClient instance in via options.
I've found countless questions about this same error, but the solutions are either already in place or irrelevant. Here is what I've found so far:
- Wrap the App with the
<ApolloProvider client={client}>
tag (this is already there in the 3 projects - but not in the "components" library) - use the
@apollo/client
package instead of the@apollo/react-hooks
- link (already using that package)
Solution 1:[1]
The solution that worked for me was to define @apollo/client
as a peer dependency in the root package.json
of my shared lirbary (I'm using lerna).
It didn't work for me to just link the package with yarn link
but I had to publish it on npm.
Solution 2:[2]
I looked into this a little more given Kn3cht's information that the shared component works if published to NPM and found a beautiful solution. There is a utility called yalc that works perfectly. The problem with npm/yarn link is that symlinked dependencies are not deduped. To use, install yalc globally (eg, npm install yalc --global or yarn global add yalc).
Let's say the component to be shared is called shared-component.
- In the root folder of shared_component, type 'yalc push'.
- In the root folder of component that will import the shared_component, type 'yalc link shared-component'
That's it. I can't believe this utility is not more widely known. I believe you still need to designate react and apollo dependencies as peerDependencies in package.json.
As for Lerna, there is a small wiring needed to have updates automatically pushed whenever the shared-component changes. Essentially, install watch at the root of the mono repo as a dev dependency, then add scripts to the root and all component package.json files that you want to have automatically pushed. For example, the target I create is called "watch:push". In the root package.json:
"scripts": {
"watch:push": "lerna run watch:push"
}
For each component that I want to share I add this target to its package.json:
"scripts": {
"push": "yalc push",
"watch:push": "watch 'yarn push' ./dist",
}
Here you can manually push your shared-component via yarn push, or you can have the shared-component pushed whenever the contents of the build folder have changed (in my case the folder is dist).
So to make this fully automatic, you need to run run a command separately that executes a build whenever source code changes.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Kn3cht |
Solution 2 | Scott |