Home > Mobile >  useSWR with getServerSideProps and GraphQL returns empty render when JavaScript is disabled
useSWR with getServerSideProps and GraphQL returns empty render when JavaScript is disabled

Time:09-05

Currently I'm trying to make a page with Next.js with pages/api feature pointing to graphql with graphql-yoga dependency and getting the data from mongoose http://localhost:3000/api/graphql.

My goal is to make a SSR page with combining getServerSideProps() and swr for data fetcher to get data from GraphQL URL.

I successfully did that, but the problem is when I disable JavaScript (in Chrome) and then refresh the page the data and CSS is not rendering as expected.

Before ( Javascript Enabled )

enter image description here

After ( Javascript Disabled )

enter image description here

Here is my Source Code:

pages/api/graphql.js:

import { createServer } from '@graphql-yoga/node'
import resolvers from 'models/graphql/resolvers'
import typeDefs from 'models/graphql/typeDefs'
import dbConnect from '../../dbConnect'

dbConnect()
const server = createServer({
    schema: {
        typeDefs,
        resolvers,
    },
    endpoint: '/api/graphql',
})

export default server

dbConnect.js

const mongoose = require('mongoose')

const MongoDb = process.env.MONGODB_URI

const connectDb = async () => {
    try {
        await mongoose.connect(MongoDb, {
            useNewUrlParser: true,
            useUnifiedTopology: true
        })
        console.log('db success connect')
    } catch (err) {
        console.log('error connecting to database')
        console.log(err)
        process.exit(1)
    }
}

export default connectDb

index.js

import Home from "components/home";
import useSWR, { SWRConfig } from "swr";
import booksQuery from 'models/graphql/queries/books'

const graphqlUrl = "http://localhost:3000/api/graphql";

const fetcher = (query) =>
    fetch(graphqlUrl, {
        method: 'POST',
        headers: {
            'Content-type': 'application/json',
        },
        body: JSON.stringify({ query }),
    })
        .then((res) => res.json())
        .then((json) => json.data)


export async function getServerSideProps() {
    const repoInfo = await fetcher(booksQuery);
    return {
        props: {
            fallback: {
                [graphqlUrl]: repoInfo
            }
        }
    };
}

function Repo() {
    const { data, error } = useSWR(booksQuery, fetcher);
    if (error) return "An error has occurred.";
    if (!data) return "Loading...";
    const { books} = data
    return <Home data={books} />

}

export default function Index({ fallback }) {
    return (
        <SWRConfig value={{fallback}}>
            <Repo />
        </SWRConfig>
    )
}

How did this happen and what is the solution to make the render the same as with JavaScript enabled?

CodePudding user response:

When javascript in the browser is disabled, the contents loading from the server only works (SSR). The contents painted from the client side (dynamic DOM CSS) won't work.

For better handling, you can show a message to the user using noscript. noscrirpt will run when javascript is disabled.

<noscript>
    <img src="no_js.gif" alt="Javascript not enabled" />
</noscript>

CodePudding user response:

The key in the useSWR call needs to match the fallback key used in getServerSideProps.

In your case this means you should use the booksQuery value as a key rather than graphqlUrl, so it matches in both situations.

export async function getServerSideProps() {
    const repoInfo = await fetcher(booksQuery);
    return {
        props: {
            fallback: {
                [booksQuery]: repoInfo
            }
        }
    };
}
const { data, error } = useSWR(booksQuery, fetcher);
//                             ^ Same key value as `fallback`. `data` will be populated correctly during SSR.
  • Related