I'm having some problem integrating Apollo Client with GatsbyJS. When I run gatsby develop everything seems to be working fine and I can use Apollo Client without any problem. However, I keep getting errors when I run gatsby build, specifically I keep getting the following error: WebpackError: Invariant Violation: Could not find "client" in the context of ApolloConsumer. Wrap the root component in an <ApolloProvider>
I can't seem to figure where this problem is coming from. Here are all my files that concern Apollo Client.
This is the client.js file:
// client.js
import {ApolloClient} from 'apollo-boost';
import {InMemoryCache} from 'apollo-cache-inmemory';
import { split } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
import fetch from 'isomorphic-fetch';
const httpLink = new HttpLink({
uri: 'https://api.emaildrop.io/graphql'
});
// Create a WebSocket link:
const wsLink = new WebSocketLink({
uri: `wss://api.emaildrop.io/subscriptions`,
options: {
reconnect: true
}
});
const link = split(
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
);
const cache = new InMemoryCache();
export const client = new ApolloClient({
link,
cache,
fetch
});
This is the wrap-root-element.js file
// wrap-root-element.js
import React from 'react';
import {ApolloProvider} from 'react-apollo';
import {client} from './client';
export const wrapRootElement = ({ element }) => (
<ApolloProvider client={client}>
{element}
</ApolloProvider>
)
This is the gatsby-browser.js file
export {wrapRootElement} from './src/apollo/wrap-root-element'
Finally, this is the gatsby-srr.js file
// gatsby-srr.js
export {wrapRootElement} from './src/apollo/wrap-root-element'
Like, I've said previously I've successfully integrated Apollo Client with GatsbyJS however, I can't seem to build it for production. This the error I get when I build it via gatsby build:
error Building static HTML for pages failed
See our docs page on debugging HTML builds for help https://gatsby.app/debug-html
38 | var args = [a, b, c, d, e, f];
39 | var argIndex = 0;
> 40 | error = new Error(
| ^
41 | format.replace(/%s/g, function() { return args[argIndex++]; })
42 | );
43 | error.name = 'Invariant Violation';
WebpackError: Invariant Violation: Could not find "client" in the context of ApolloConsumer. Wrap the root component in an <ApolloProvider>
- invariant.js:40 invariant
[lib]/[invariant]/invariant.js:40:1
- ApolloConsumer.js:4 ApolloConsumer
[lib]/[react-apollo]/ApolloConsumer.js:4:1
- bootstrap:25 a.render
lib/webpack/bootstrap:25:1
- bootstrap:24 a.read
lib/webpack/bootstrap:24:1
- bootstrap:36 renderToString
lib/webpack/bootstrap:36:1
- static-entry.js:190 Module.default
lib/.cache/static-entry.js:190:18
- bootstrap:24 Promise
lib/webpack/bootstrap:24:1
- gatsby-browser-entry.js:3 Promise._resolveFromExecutor
lib/.cache/gatsby-browser-entry.js:3:1
- bootstrap:68 new Promise
lib/webpack/bootstrap:68:1
- bootstrap:5 tryCatcher
lib/webpack/bootstrap:5:1
- bootstrap:50 MappingPromiseArray._promiseFulfilled
lib/webpack/bootstrap:50:1
- api-runner-ssr.js:8 MappingPromiseArray.PromiseArray._iterate
lib/.cache/api-runner-ssr.js:8:1
You'll want to implement replaceRenderer in gatsby-ssr.js.
See this thread - https://github.com/gatsbyjs/gatsby/issues/3650
Related
The Problem:
I'm building a blog with Next and sanity. When navigating to /blog, i'm encountering this error in the browser:
./sanity.js:2:0
Module not found: Can't resolve '#sanity/image-url'
1 | import { createCurrentUserHook, createClient } from "next-sanity";
> 2 | import imageUrlBuilder from "#sanity/image-url";
3 |
4 | export const config = {
5 | // Find your project ID and dataset in 'sanity.json' in your studio project.
Import trace for requested module:
./pages/blog.tsx
https://nextjs.org/docs/messages/module-not-found
The folder structure is:
root
-> components
-> pages
-> post
-> [slug].tsx
-> index.tsx
-> blog.tsx
-> sanity subfolder
-> public
-> styles
sanity.js (config file)
The sanity config file
I have a sanity config file, which exports some helper functions. One of which, is the imageUrlBuilder function, which i'm assuming the error is coming from. Here is my sanity config file: Note: this is pulled from sanity docs.
import { createCurrentUserHook, createClient } from "next-sanity";
import imageUrlBuilder from "#sanity/image-url";
export const config = {
// config info here
};
// Set up the client for fetching data in the getProps page functions.
export const sanityClient = createClient(config);
// Builder function to combo with urlFor function.
const builder = imageUrlBuilder(sanityClient);
// Helper function to generate urls from sanity photos.
export const urlFor = (source) => {
return builder.image(source);
};
The helper function was working in a previous version, and was able to pull images from sanity and display in the document. But i'm unsure why it's causing issues with page routing.
The blog page component:
import React from "react";
import BlogPreview from "../components/BlogPreview";
import { getAllPosts } from "../queries";
import { sanityClient } from "../sanity";
import { Post } from "../typings";
interface Props {
posts: [Post];
}
// required for server-side rendering. returns 'props' object from db.
export const getServerSideProps = async () => {
let query = getAllPosts;
const posts = await sanityClient.fetch(query);
return {
props: {
posts,
},
};
};
function blog({ posts }: Props) {
return (
<div>
<div className='md:grid md:grid-cols-2'>
{posts.map((post) => {
return (
<BlogPreview
key={post._id}
title={post.title}
description={post.description}
mainImage={post.mainImage}
slug={post.slug}
/>
);
})}
</div>
</div>
);
}
export default blog;
I've tried:
Logging sanity data to the console to check for config errors.
Googling the error: Module not found: Can't resolve '#sanity/image-url'
Conclusion
I'm unsure what the issue is, and how I can potentially solve it. Would love some ideas.
Thanks in advance
It sounds like you don't have the #sanity/image-url module installed in your project.
Run this in your project directory and you should be good to go!
npm install --save #sanity/image-url
I am trying to use the expo-camera for web. For reference, this is working 100% on Expo Go on my phone. But when I visit my website (hosted on AWS) which has the same build, I get a white screen after accepting camera permissions because of this 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.
I can see in chrome tools (attached to my phone) this error, but it doesn't look like anything I am doing..
react-native-logs.fx.ts:34 Error: Minified React error #321; visit https://reactjs.org/docs/error-decoder.html?invariant=321 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
at V (react.production.min.js:19)
at Object.t.useRef (react.production.min.js:25)
at ExponentCamera.web.tsx:30
at na (react-dom.production.min.js:157)
at Ia (react-dom.production.min.js:176)
at Bs (react-dom.production.min.js:271)
at Sl (react-dom.production.min.js:250)
at _l (react-dom.production.min.js:250)
at wl (react-dom.production.min.js:250)
at dl (react-dom.production.min.js:243)
And this is the code it is referring to, which is of course part of expo
const ExponentCamera = React.forwardRef(
(
{ type, pictureSize, poster, ...props }: CameraNativeProps & { children?: React.ReactNode },
ref: React.Ref<ExponentCameraRef>
) => {
const video = React.useRef<HTMLVideoElement | null>(null);
const native = useWebCameraStream(video, type as CameraType, props, {
onCameraReady() {
if (props.onCameraReady) {
props.onCameraReady();
}
},
onMountError: props.onMountError,
});
Here is my code
import React from 'react';
import { StyleSheet, Text } from 'react-native';
import { NavigationProp, ParamListBase } from '#react-navigation/native';
import { BarCodeScanningResult, Camera, PermissionResponse, PermissionStatus } from 'expo-camera';
export interface BarCodeScannerScreenProps {
navigation: NavigationProp<ParamListBase>
}
export const BarCodeScannerScreen = (props: BarCodeScannerScreenProps) => {
const [cameraPermission, setCameraPermission] = React.useState<string>(PermissionStatus.UNDETERMINED);
const getPermission = async () => {
const response: PermissionResponse = await Camera.requestCameraPermissionsAsync();
setCameraPermission(response.status);
};
const onBarCodeScanned = (event: BarCodeScanningResult) => {
props.navigation.navigate("BookSearch", {searchValue: event.data});
};
React.useEffect(() => {
getPermission();
}, []);
if(cameraPermission === PermissionStatus.UNDETERMINED){
return <Text>Requesting camera permission</Text>;
}
else if(cameraPermission === PermissionStatus.GRANTED){
return (
<Camera
onBarCodeScanned={onBarCodeScanned}
style={StyleSheet.absoluteFill}
/>
);
}
else {
return <Text>No access to camera</Text>;
}
}
Maybe I do have some invalid hook or something in my code? But I don't see why it would work fine on Expo Go.
The recipe from a React issue comment worked for me:
expo customize:web
select webpack (PRESS SPACE)
enter
Then modify webpack.config.js file this way:
const createExpoWebpackConfigAsync = require('#expo/webpack-config');
const path = require('path');
module.exports = async function (env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
// Customize the config before returning it.
config.resolve.alias = {
react: path.resolve('./node_modules/react')
}
return config;
};
After executing my React Native app I've ran into this error:
Could not find "client" in the context or props of Mutation. Wrap the root component in an <ApolloProvider>, or pass an ApolloClient instance via props.
Here's my apollo client
import { Platform } from "react-native";
import { ApolloClient, InMemoryCache } from "#apollo/client";
// To access our host machine and not the device itself we use a special ip on android
// If we are using IOS access localhost:4000 else use 10.0.0.2:4000
const host =
Platform.OS === "ios" ? "http://localhost:4000" : "http://10.0.2.2:4000";
export const client = new ApolloClient({
uri: host,
cache: new InMemoryCache(),
});
And here's index.tsx which wraps my root component:
import { ApolloProvider } from '#apollo/client';
import { client } from "./apollo";
import { Routes } from "./routes/index";
export default class App extends React.PureComponent {
render() {
return (
<ApolloProvider client={client}>
<Routes />
</ApolloProvider>
);
}
}
Before V 3.0 react-apollo and apollo-client (And other sub-packages) were on separate packages (Made a lot of issues/errors related to packages versions. Issue 2042 -or- issue 2900).
The best idea is to Migrating to Apollo Client 3.0.
The react-apollo package has been deprecated, and the functionality
offered by each of the above packages can now be accessed from
#apollo/client. Migrating to Apollo Client 3.0
Apollo V3.0 Great "get-started"/tuturial example + sandbox:
https://www.apollographql.com/docs/react/get-started/
client
In your case looks like the client is undefined. Run and test:
console.log(client); /* return object -or- not? */
Try to run this code in one file (If this code works fine - separate the files you want and use module.exports).
import React from "react";
import { render } from "react-dom";
import {
ApolloClient,
InMemoryCache,
ApolloProvider,
useQuery,
gql
} from "#apollo/client";
export const client = new ApolloClient({
uri: "https://48p1r2roz4.sse.codesandbox.io",
cache: new InMemoryCache()
});
export default class App extends React.PureComponent {
render() {
return (
<ApolloProvider client={client}>
<h2>My first Apollo app <span>🚀</span></h2>
</ApolloProvider>
);
}
}
render(<App/>, document.getElementById("root"));
I currently have an application built with CRA which uses React Router. I'm now trying to have a part of my application be rendered via Gatsby so that non technical users can control the content of this part of the application via a CMS.
What I have currently works in the dev server, but dies when I try and build.
This is my gatsby-node
exports.onCreatePage = async ({ actions, page }) => {
const { createPage } = actions;
return new Promise((resolve, reject) => {
if (page.path === "/") {
createPage({
...page,
matchPath: "/*"
});
}
resolve();
});
};
I have a static page that is being rendered at pages/study/index.js. It's quite large, so assume it looks like this
export default function Home({ data }) {
if (!data) return null;
const { mdx } = data;
const { frontmatter: cmsData } = mdx;
return (
<StaticRouter location="/study">
<Provider>
<HomeTemplateWithRouter cmsData={cmsData} data={data} />
</Provider>
</StaticRouter>
);
}
I also have an index.js which looks like this
import React from "react";
import { Provider } from "components/general/Provider";
import { BrowserRouter } from "react-router-dom";
import AppContainer from "containers/AppContainer";
import { StaticRouter } from "react-router";
const Application = () => {
return (
<BrowserRouter>
<Provider>
<AppContainer />
</Provider>
</BrowserRouter>
);
};
export default Application;
Everything works when I use the development server. However when I build I get this error
Building static HTML failed for path "/"
See our docs page for more info on this error: https://gatsby.dev/debug-html
7 |
8 | if (isProduction) {
> 9 | throw new Error(prefix);
| ^
10 | } else {
11 | throw new Error(prefix + ": " + (message || ''));
12 | }
WebpackError: Invariant failed
- tiny-invariant.esm.js:9 invariant
node_modules/tiny-invariant/dist/tiny-invariant.esm.js:9:1
- history.js:250 createBrowserHistory
node_modules/history/esm/history.js:250:115
- BrowserRouter.js:29 new BrowserRouter
node_modules/react-router-dom/es/BrowserRouter.js:29:176
Why is this happening only when I build a production version of the website?
Why is this happening given that I've defined a client side route and the code here should only be rendered client side?
What is the way around this without changing my dependency on react-router?
Thanks!
I have the same problem. I search on the Internet and find only one solution is to avoid react-router-dom.
I finally finished my backend with apollo.
Now I moved to the frontend.
I made it work with the normal http connection and fetched some messages from the server (chat app).
Now I also tried to connect the subscription link to it (which was very confusing in itself because there are a few examples outside and everybody does it a bit differently, but neither worked).
So here is how my index file looks on react frontend:
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { ApolloClient } from "apollo-client";
import { ApolloProvider } from "react-apollo";
import { WebSocketLink } from "apollo-link-ws";
import { ApolloLink } from "apollo-link";
import { HttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/graphql`,
options: {
reconnect: true
}
});
// Create an http link:
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql"
});
const link = ApolloLink.from([httpLink, wsLink]);
const client = new ApolloClient({
link,
cache: new InMemoryCache()
});
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById("root")
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
I also tried different methods for example with split from apollo-link like this:
const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
wsLink,
httpLink
);
I also tried it with ApolloClient from apollo-boost instead of apollo-client.
Can somebody please help me out, because I can't get it to work.
Error message is always:
WebSocket connection to 'ws://localhost:4000/graphql' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
If you want to see the full code: https://github.com/SelfDevTV/graphql-simple-chat