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.
Related
I'm trying to generate the page from the server side page on Next.js, But I'm having a problem with it, so I have created an Apollo instance and I'm importing a Query from my queries, and I pass the variable as I do on useQuery from apollo on the client, because I don't know another way to do that, also how to handle errors on this?
Here are my getServerSideProps:
export async function getServerSideProps(context) {
const slug = context.params.slug;
const data = await Static.query({
query: LANDING,
variables: { slug },
});
return {
props: {
data: data,
},
};
}
Here is my query:
import gql from "graphql-tag";
export const CATEGORIES = gql`
query CategoriesView {
CategoriesView {
_id
Name
Description
Icon
}
}
`;
Here is my Client:
import {
ApolloClient,
HttpLink,
ApolloLink,
InMemoryCache,
} from "#apollo/client";
const uri = "http://localhost:3000/api"
const httpLink = new HttpLink({uri});
export const Apollo = new ApolloClient({
ssr: typeof window === "undefined" ? true : false,
cache: new InMemoryCache(),
link: ApolloLink.from([httpLink]),
});
But I get this error: failed to fetch
Here is a screenshot of it:
Here is my example, working in my case.
import { useSubscription, useQuery, gql } from "#apollo/client";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
//your query here ; first check if your query works (use your playground)
const QUERY = gql`
query {
customers{
data{
attributes{
firstname
lastname
location
phone
createdAt
}
}
}
}
`;
const Page = () => {
//apollo function
const { data, loading, error } = useQuery(QUERY);
if (loading) return <div>Loading...</div>
if (error) return <div>Failed to load!</div>
return (
<>
{JSON.stringify(data)}
</>
)
};
//can do with staticProps, serverProps, etc. Below just an example - delete if not needed
export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations(locale, ["common"])),
},
};
}
export default Page;
I am not sure if you can put gql query in getServerSideProps because apollo creates some sort of "cache" for your queries.
And check #apollo/client library
Apollo client fails to do query when initialized with SchemaLink (nexus) instead of HttpLink. I get this error Cannot set properties of undefined (setting 'select')
function createIsomorphLink() {
if (typeof window === 'undefined') {
const { SchemaLink } = require('#apollo/client/link/schema')
const { schema } = require('./nexusSchema')
return new SchemaLink({ schema })
} else {
const { HttpLink } = require('#apollo/client/link/http')
return new HttpLink({
uri: '/api/graphql',
credentials: 'same-origin',
})
}
}
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: from([errorLink, createIsomorphLink()]),
cache: new InMemoryCache(),
})
}
Here's my getServerSideProps. I initialize apollo client and use apolloClient.query(...)
export const getServerSideProps = async ({ params }) => {
const id = params.id
const apolloClient = initializeApollo()
// Here's where the error occurs
const { data } = await apolloClient.query({
query: gql`
query findUniquePage($id: String!) {
findUniquePage(where: { id: $id }) {
title
type
content
isPublished
}
}
`,
variables: { id },
})
// ...snippet..
}
I tried creating simple 'hello' query with string response, so that there was no select part. But error stayed the same.
export const getServerSideProps = async () => {
const apolloClient = initializeApollo()
const { data } = await apolloClient.query({
query: gql`query hello { hello }`,
})
return {
props: {},
}
}
My apollo client version is 3.7.0. The latest is 3.7.1 but by CHANGELOG there seems to be nothing that addresses my issue. Probably, the problem is how apollo client requests my api via SchemaLink, or how my api parses that request (apollo server + code first nexus). Because when I replaced SchemaLink with HttpLink, code worked fine. But I kinda want to keep the SchemaLink. Any advice?
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.
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
}
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;
}