Edit: is this not working because I'm not calling getInitialProps
? NextJS documentation (https://nextjs.org/docs/basic-features/data-fetching#server-side-rendering) says that if you don't then the page is statically rendered at build time. So I should put my useQuery
inside getInitialProps
?
I'm testing out an Apollo Client front end that connects through GraphQL to a KeystoneJS CMS backend. One method of testing whether SSR is working is, as I understand it, to load a page in a browser, check the source and see if the HTML is in there. It's not working for me.
The page source is as follows (it's ugly, I'm just testing out that connections and SSR work):
import React from 'react';
import Head from 'next/head';
import {useQuery} from '@apollo/react-hooks';
import gql from 'graphql-tag';
const ARTICLES_QUERY = gql`
query {
allArticles {
title
text
}
}
`;
const Home = () => {
// Create a query hook
const {data, loading, error} = useQuery(ARTICLES_QUERY);
console.log(data)
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error: {JSON.stringify(error)}</p>;
}
return (
<div>
<Head>
<title>Home</title>
<link rel="icon" href="/favicon.ico"/>
</Head>
<p>some paragraph text</p>
<div>And something in a div</div>
<ul>
{data?.allArticles?.map(article => {
return <li key={`article__${article.title}`}>{article.title}</li>;
})}
</ul>
</div>
);
};
export default Home;
The page renders as
and the page source for that page is
<!DOCTYPE html><html><head><style data-next-hide-fouc="true">body{display:none}</style><noscript data-next-hide-fouc="true"><style>body{display:block}</style></noscript><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/development/pages/index.js?ts=1582296618319" as="script"/><link rel="preload" href="/_next/static/development/pages/_app.js?ts=1582296618319" as="script"/><link rel="preload" href="/_next/static/runtime/webpack.js?ts=1582296618319" as="script"/><link rel="preload" href="/_next/static/runtime/main.js?ts=1582296618319" as="script"/><noscript id="__next_css__DO_NOT_USE__"></noscript></head><body><div id="__next"><p>Loading...</p></div><script src="/_next/static/development/dll/dll_d6a88dbe3071bd165157.js?ts=1582296618319"></script><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{},"apolloState":{},"apollo":null},"page":"/","query":{},"buildId":"development","isFallback":false}</script><script nomodule="" src="/_next/static/runtime/polyfills.js?ts=1582296618319"></script><script async="" data-next-page="/" src="/_next/static/development/pages/index.js?ts=1582296618319"></script><script async="" data-next-page="/_app" src="/_next/static/development/pages/_app.js?ts=1582296618319"></script><script src="/_next/static/runtime/webpack.js?ts=1582296618319" async=""></script><script src="/_next/static/runtime/main.js?ts=1582296618319" async=""></script><script src="/_next/static/development/_buildManifest.js?ts=1582296618319" async=""></script></body></html>
Neither my static HTML nor the dynamic content is in there.
I am missing something obvious here? Is it the Apollo Client cache? Is it something I'm missing about how NextJS should work? This is all on first page load -- that is, I know it's client-side rendered when you navigate on client side, but this should come straight from the server, no?
For what it's worth, pages/_app.js
is
import React from 'react';
import App from 'next/app';
import { ApolloProvider } from '@apollo/react-hooks';
import withData from '../util/apollo-client';
class MyApp extends App {
render() {
const { Component, pageProps, apollo } = this.props;
return (
<ApolloProvider client={apollo}>
<Component {...pageProps} />
</ApolloProvider>
);
}
}
// Wraps all components in the tree with the data provider
export default withData(MyApp)
and /util/apollo-client.js
is
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import withApollo from 'next-with-apollo';
import { createHttpLink } from 'apollo-link-http';
import fetch from 'isomorphic-unfetch';
// Update the GraphQL endpoint to any instance of GraphQL that you like
const GRAPHQL_URL = 'http://localhost:3000/admin/api';
const link = createHttpLink({
fetch, // Switches between unfetch & node-fetch for client & server.
uri: GRAPHQL_URL
});
// Export a HOC from next-with-apollo
// Docs: https://www.npmjs.com/package/next-with-apollo
export default withApollo(
// You can get headers and ctx (context) from the callback params
// e.g. ({ headers, ctx, initialState })
({ initialState }) =>
new ApolloClient({
link: link,
cache: new InMemoryCache()
// rehydrate the cache using the initial data passed from the server:
.restore(initialState || {})
})
);
I think ApolloClient
is missing ssrMode
option
Include the option into your withApollo
function as follows:
Example:
// Export a HOC from next-with-apollo
// Docs: https://www.npmjs.com/package/next-with-apollo
export default withApollo(
// You can get headers and ctx (context) from the callback params
// e.g. ({ headers, ctx, initialState })
({ initialState, ctx }) =>
new ApolloClient({
ssrMode: Boolean(ctx),
link: link,
cache: new InMemoryCache()
// rehydrate the cache using the initial data passed from the server:
.restore(initialState || {})
})
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With