I am experiencing this weird error in Apollo that I am unable to fix. Any help is greatly appreciated!
So the issue is that Apollo works just fine when I load the webpage from my laptop but problems start when I load the webpage from my phone. The error is as follows:
Here is the full error from the console on the phone.
I also have a custom apollo client setup as mentioned in this page: https://www.apollographql.com/blog/building-a-next-js-app-with-apollo-client-slash-graphql/
It's similar to the one below:
import { useMemo } from "react";
import {
InMemoryCache,
ApolloClient,
HttpLink,
NormalizedCacheObject,
} from "#apollo/client";
let apolloClient: ApolloClient<NormalizedCacheObject>;
const createApolloClient = () => {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: new HttpLink({
uri: process.env.API_ENDPOINT,
}),
cache: new InMemoryCache(),
});
};
export function initializeApollo(initialState: object | null = null) {
const _apolloClient = apolloClient ?? createApolloClient();
// If your page has Next.js data fetching methods that use Apollo Client,
// the initial state gets hydrated here
if (initialState) {
// Get existing cache, loaded during client side data fetching
const existingCache = _apolloClient.extract();
// Restore the cache using the data passed from
// getStaticProps/getServerSideProps combined with the existing cached data
_apolloClient.cache.restore({ ...existingCache, ...initialState });
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === "undefined") return _apolloClient;
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
}
export function useApollo(initialState: object) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
}
Related
I'm trying to convert a vue3 SPA that uses an apollo client to SSR with the help of vite-plugin-ssr.
I'm facing an issue of mixed-up data on concurrent requests to the express server. The apollo client instance used to be global in the SPA, so I'm trying to create and use a new instance on every request.
I had this file that included the creation of the client, and wrapper functions around the client functions :
// apollo.ts - SPA
const apolloClient = new ApolloClient({
...
})
export const apolloQuery = async (args) => {
// some logic
const response = await apolloClient.query({...})
// some logic
return response
}
...
Those functions are used in components and store.
The integration example of apollo in vite-plugin-ssr repo uses #vue/apollo-composable
So I tried :
// app.ts
import { DefaultApolloClient } from "#vue/apollo-composable";
import { createApolloClient } from "./path/to/apollo.ts";
const createApp = () => {
const apolloClient = createApolloClient({...})
const app = createSSRApp({
setup() {
provide(DefaultApolloClient, apolloClient)
},
render() {
return h(App, pageProps || {});
}
});
}
// apollo.ts - SSR
import { useApolloClient } from "#vue/apollo-composable"
export const createApolloClient = (args) => {
// some logic
return new ApolloClient({...})
}
export const apolloQuery = async (args) => {
// some logic
const { client } = useApolloClient()
const response = await client.query({...})
// some logic
return response
}
However, this does not work as intended because useApolloClient depends on providing the apollo instance to the app (1), or using the provideApolloClient function (2) :
(1) this means that calls can only be made during component setup or life cycle hooks, as it leverages the Vue core function getCurrentInstance to inject the client. So I can neither use them in the onBeforeRender that vite-plugin-ssr provides, nor in Vue onServerPrefetch hook, nor in the async call to store action.
(2) provideApolloClient sets the client to a global variable, and the same problem occurs on concurrent requests.
Am I at a dead end and a complete refactor of the apollo client use is needed, or am I missing something?
I'm trying to use NextJS with Apollo, but I can't understand where should I insert my dataSources, so I'd be able to access it through context in my resolvers (as stated in the docs).
Here's my apollo.ts (the same from NextJS with-typescript-graphql example):
import { IncomingMessage, ServerResponse } from 'http'
import { useMemo } from 'react'
import {
ApolloClient,
InMemoryCache,
NormalizedCacheObject,
} from '#apollo/client'
import resolvers from './resolvers'
import typeDefs from './schema'
let apolloClient: ApolloClient<NormalizedCacheObject> | undefined
export type ResolverContext = {
req?: IncomingMessage
res?: ServerResponse
}
function createIsomorphLink(context: ResolverContext = {}) {
if (typeof window === 'undefined') {
const { SchemaLink } = require('#apollo/client/link/schema')
const { makeExecutableSchema } = require('#graphql-tools/schema')
const schema = makeExecutableSchema({
typeDefs,
resolvers,
})
return new SchemaLink({ schema, context })
} else {
const { HttpLink } = require('#apollo/client')
return new HttpLink({
uri: '/api/graphql',
credentials: 'same-origin',
})
}
}
function createApolloClient(context?: ResolverContext) {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: createIsomorphLink(context),
cache: new InMemoryCache(),
})
}
export function initializeApollo(
initialState: any = null,
// Pages with Next.js data fetching methods, like `getStaticProps`, can send
// a custom context which will be used by `SchemaLink` to server render pages
context?: ResolverContext
) {
const _apolloClient = apolloClient ?? createApolloClient(context)
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// get hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState)
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient
return _apolloClient
}
export function useApollo(initialState: any) {
const store = useMemo(() => initializeApollo(initialState), [initialState])
return store
}
I tried to put it alonside with typeDefs in the parameters for makeExecutable, but it's still undefined when I try to use it.
My confusion is because this setup doesn't use the new ApolloServer() constructor, as the example in the docs and I can't find some docs which relates to my setup.
I'm trying to utilise SSR with apollo & graphql. I have followed all of the various advice on stack overflow and elsewhere but cannot seem to clear this error:
Error: Expected undefined to be a GraphQL schema.
I cannot understand this error at all. The query is not undefined; I'm using a valid graphql schema.
I've also tried downgrading to graphql 15, as that was suggested on another post. No luck, though.
Here's my current code:
// [id].js
const event = gql`
fragment event on Event {
id
name
date
location
imageUrl
description
}
`
const getEvent = gql`
query getEvent($id: Int!) {
event(id: $id) {
...event
}
}
${event}
`
export const getServerSideProps = async ({ params }) => {
const client = initializeApollo()
const test = await client.query({
query: getEvent,
variables: {
id: parseInt(params.id),
},
})
return {
props: {
eventId: params.id,
test,
},
}
}
We are using the ApolloProvider in the rest of the app because we are doing CSR, and as I understand it we need to create a new client in our getServerSideProps, which you can see I'm doing above.
initializeApollo is the same code as you see in a lot of tutorials, even from Apollo themselves:
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: createIsomorphLink(),
cache: new InMemoryCache(),
})
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient()
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// gets hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState)
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient
return _apolloClient
}
Any pointers would be much appreciated.
I have setup Next.js (11) app with working connection to the firebase version 8.7.
I got an issue on getting donwload URL for image:
If I'd create a function (example below) to fetch the uploaded image - assume it is there & I know its name and location. It will work only once (dev env)
After any route change or page refresh (not on code change assuming I do not change the route or refresh the page), the app crashes with terminal error:
ReferenceError: XMLHttpRequest is not defined
I get this error when I call both in getStaticProps or in the component itself on the client side
function example:
import firebase from "firebase/app";
import "firebase/storage";
export const getImgUrl = async () => {
const storage = firebase.storage();
const pathReference = storage.ref("user_uploads/my_image.jpg");
pathReference
.getDownloadURL()
.then((url) => {
console.log("my url", url);
})
.catch((error) => {
console.error("error", error);
});
};
I have a bypass solution:
Upgrade to the firebase sdk version 9 (modular one).
Create db & storage:
const initFirebase = () => {
const db = getFirestore(firebaseApp)
const storage = getStorage(firebaseApp)
console.log('Firebase was successfully initialized')
return [db, storage]
}
// Init firebase:
export const [db, storage] = initFirebase()
use it:
const getData = async () => {
console.log('getData runs')
try {
const url = await getDownloadURL(ref(storage, 'landing/land.jpg'))
console.log('getData url:', url)
return url
} catch (error) {
// Handle any errors
}
}
and call getData in getServerSideProps or getStaticProps in any component
can you help to check my code is there anyway that i can get access token from cookie and send it through apollo client? In my Next.js project i am using NextAuth for authentication. After user logged in I save user information and access token inside session. But i have know idea how can i get it and pass it with apollo client.
import { useMemo } from 'react'
import { ApolloClient, ApolloLink, InMemoryCache, createHttpLink } from '#apollo/client'
import { setContext } from '#apollo/client/link/context';
import { concatPagination } from '#apollo/client/utilities'
import merge from 'deepmerge'
import isEqual from 'lodash/isEqual'
export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__'
let apolloClient
const CLIENT_URL =
process.env.NODE_ENV === 'production'
? process.env.API_END_POINT
: 'http://localhost:1337'
function createApolloClient() {
const httpLink = createHttpLink({
uri: `${CLIENT_URL}/graphql`,
credentials: 'same-origin'
});
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : ''
}
}
});
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
jobs: concatPagination(),
},
},
},
});
const client = new ApolloClient({
srMode: typeof window === 'undefined',
link: authLink.concat(httpLink),
cache
});
return client;
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient()
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// gets hydrated here
if (initialState) {
// Get existing cache, loaded during client side data fetching
const existingCache = _apolloClient.extract()
// Merge the existing cache into data passed from getStaticProps/getServerSideProps
const data = merge(initialState, existingCache, {
// combine arrays using object equality (like in sets)
arrayMerge: (destinationArray, sourceArray) => [
...sourceArray,
...destinationArray.filter((d) =>
sourceArray.every((s) => !isEqual(d, s))
),
],
})
// Restore the cache with the merged data
_apolloClient.cache.restore(data)
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient
return _apolloClient
}
export function addApolloState(client, pageProps) {
if (pageProps?.props) {
pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract()
}
return pageProps
}
export function useApollo(pageProps) {
const state = pageProps[APOLLO_STATE_PROP_NAME]
const store = useMemo(() => initializeApollo(state), [state])
return store
}