next.jsgraphqlserver-side-renderingurql

Next 13: how do I fetch data for server components every time there is a request with Urql Graphql


I currently have the following server component at the route /app/account/page.tsx:

const AccountPage = async () => {
    const username = await getViewer();

    return <AccountView username={username} />;
};

I expect getViewer to be run every time there is a request. However, this is not the case. When I debug the backend code that is supposed to be hit by getViewer, it doesn't get hit when I navigate to /account. How can I make it so this server code runs on each request? Note that I can't use the updated fetch API in my case because I'm using a GraphQL API and urql for making requests.

Edit: The setup for my urql client and the function used by getViewer for using my API is the following:

import { Client, TypedDocumentNode, createClient } from 'urql/core';

const query = async <
    TResponse,
    TVariables extends { [prop: string]: any } = Record<string, unknown>
>(
    queryString: string | DocumentNode | TypedDocumentNode,
    {
        variables,
        client,
        cache
    }: { variables?: TVariables; client?: Client; cache?: RequestCache } = {}
) =>
    await (
        client ??
        createClient({
            url: `/api/graphql`,
            fetchOptions: {
                cache: cache ?? 'no-store'
            },
            requestPolicy: 'network-only',
            fetch
        })
    )
        .query<TResponse>(queryString, variables)
        .toPromise();

Edit2: Adding more details for anyone trying to reproduce the issue

getViewer is as follows:

export const getViewer = async ({
    client,
    cache
}: { client?: Client; cache?: CacheType } = {}) =>
    (await query<{ viewer: string }>(GET_SPELL, { client, cache })).data?.viewer;

GraphQL schema:

type Query {
    viewer: String
}

GraphQL resolver:

const Query = {
    viewer: () => {
        console.log('Hitting the viewer endpoint!');
        return 'Dummy username';
    }
}

The GraphQL server gets run from /pages/api/graphql.ts, which has the following code:

import { ApolloServer } from 'apollo-server-micro';
import Cors from 'micro-cors';
import schema from '../../src/graphql/server/schema';

const cors = Cors();

const apolloServer = new ApolloServer({
    schema,
});

export const config = {
    api: {
        bodyParser: false
    }
};

const startServer = apolloServer.start();

export default cors(async (req, res) => {
    if (req.method === 'OPTIONS') {
        res.end();
        return false;
    }

    await startServer;
    await apolloServer.createHandler({ path: '/api/graphql' })(req, res);
});

Next version: 13.0.5.

Urql version: 3.0.3

Hopefully this should be enough information for anyone trying to reproduce the issue.


Solution

  • I realized that I had a few things wrong that had nothing to do with what I thought the problem was.

    First, when defining the urql client on the server, you need to have an absolute path. The path I was using, /api/graphql, was only realtive and thus failing.

    Another error I noticed is that I am using the wrong query. It should have been GET_VIEWER, but was GET_SPELL. I managed to get the expected behavior once I addressed these things.