I am making a chat application in NextJS using a Graphql subscription.
I tried to find some examples but all I found were either expressjs with reactjs or expressjs with nextjs.
I used graphql-yoga
in nextjs serverless and graphql apollo
in frontend.
The following error is what I see now in the terminal.
error - TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received type function ([Function (anonymous)])
I am not sure what is causing this issue.
Here is the backend for my nextjs
import { createServer, createPubSub } from "@graphql-yoga/node";
const pubsub = createPubSub();
const NEW_MESSAGE = "NEW_MESSAGE";
const NEW_MESSAGES = "NEW_MESSAGES";
const messages = [];
const resolvers = {
Query: {
messages: (_, { name }, context) => messages,
},
Mutation: {
createMessage(parent, { user, body }, { pubsub }) {
const id = Math.floor(Math.random() * 10000000);
messages.push({ id, user, body });
pubsub.publish(NEW_MESSAGE, {
newMessage: { id, user, body },
});
pubsub.publish(NEW_MESSAGES);
return true;
},
},
Subscription: {
newMessage: {
subscribe: (_, __, { pubsub }) => {
return pubsub.subscribe(NEW_MESSAGE);
},
resolve: (payload) => {
const { message } = payload;
const { id, user, body } = message;
return { id, user, body };
},
},
newMessages: {
subscribe: (_, __, { pubsub }) => {
return pubsub.subscribe(NEW_MESSAGES);
},
resolve: () => messages,
},
},
};
const typeDefs = `
type Message {
id: ID!
user: String!
body: String!
}
type MessageInput {
user: String!
body: String!
}
type SubscriptionPayload {
id: ID
user: String
body: String
}
type Query {
messages: [Message!]
}
type Mutation {
createMessage(user: String!, body: String!): Boolean!
}
type Subscription {
newMessage: Message
newMessages: [Message]
}
`;
const server = createServer({
context: async ({ req }) => {
return {
user: { name: "jogn Doe", id: 0 },
pubsub,
};
},
schema: {
typeDefs,
resolvers,
},
});
export default server;
my backend seems to be working fine in the graphql yoga playground
but my frontend does not as soon as I integrate with my backend.
// _app.js
import "../styles/globals.css";
import { ApolloProvider } from "@apollo/client";
import { client } from "./apollo";
function MyApp({ Component, pageProps }) {
return (
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
);
}
export default MyApp;
// apollo.js
import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
const uri = 'localhost:3000/api/graphql';
const httpLink = new HttpLink({
uri: `http://${uri}`
});
const wsLink = () => {
return new GraphQLWsLink(createClient({
url: `ws://${uri}`
}));
}
export const client = new ApolloClient({
link: typeof window === 'undefined' ? httpLink : wsLink(),
cache: new InMemoryCache(),
});
// index.js
import Head from "next/head";
import styles from "../styles/Home.module.css";
import { gql, useSubscription } from "@apollo/client";
export default function Home() {
const SUBSCRIPTION = gql`
subscription newMessages {
newMessages {
id
user
body
}
}
`;
const { loading, error, data } = useSubscription(SUBSCRIPTION);
console.log({ data, loading, error });
console.log(error); // {Error: undefined} is printed
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<div>Hello Nextjs Graphql</div>
</main>
</div>
);
}
Why is it not working? I cannot find a valid solution. I found people also having other problems with this integration. Is NextJS backend not good for this use case as nextjs backend is serverless? If so, I do not understand why.. In that case, does using some sort of in-memory database would help such as Redis?
Thank you for reading and for your time.