1

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.

  • Don't graphql subscriptions require a websocket connection? Next's serverless functions timeout after some seconds so subscriptions won't work without a custom server. But it may be that the error is related to something else – maxeth Dec 10 '22 at 20:09

0 Answers0