next-with-apollo
next-with-apollo copied to clipboard
Request: Support next.js 9.3
Would like an update for the new version of next.js. Specifically including the new data-fetching methods and examples of use.
There's no need for this package, or of any Apollo packages at all if you want to enjoy the goodies of the latest release of Next.js.
For getStaticProps do a simple fetch for the data using a GraphQL query (you can use node-fetch or @zeit/fetch) and return it as props, there's no need to add Apollo for this case.
There's no need for this package, or of any Apollo packages at all if you want to enjoy the goodies of the latest release of Next.js.
For
getStaticPropsdo a simple fetch for the data using a GraphQL query (you can usenode-fetchor@zeit/fetch) and return it as props, there's no need to add Apollo for this case.
Ok thank you. I wasn't sure if the update would change anything with this package. Especially since its deprecates getInitialProps. Could be nice to mention in docs... But anyways thanks for responding!
@LassiterJ getInitialProps is not really deprecated and won't go away anytime soon (I'm part of the Next.js team), the package will stay as it is for now, once we see enough traction for SSG I'll update it.
add support with getServerSideProps please
export const getServerSideProps = async ({ query, res }) => {
const { slug } = query;
if (!slug && res || slug.length < 2 && res) {
res.statusCode = 404
}
// it's necesary for display 404 custom error
const { data, error } = useQuery(MOVIE_SLUG, { variables: { slug } }); // not work....
if (data && data.movie === null) {
res.statusCode = 404;
}
...
};
@juanpablocs That is not how you suppose to use useQuery hook. A React hook can only be used in a React component. getServerSideProps is like an HTTP API endpoint and is definitely not React.js.
I imagine it would be difficult to make next-with-apollo to work with getServerSideProps because getServerSideProps is completely separated from the React component.
AppTreeis not available.ssris impossible.- no way to connect
getServerSidePropsto the the component (to restore cache / apolloState,apolloprops).
Correct me if I am wrong @lfades
This would be how we may use Apollo Client in getServerSideProps and getStaticProps. This is modified from the example.
Export clientFn (first arg in withApollo):
// lib/withApollo.js
import withApollo from 'next-with-apollo';
import ApolloClient, { InMemoryCache } from 'apollo-boost';
import { ApolloProvider } from '@apollo/react-hooks';
export const clientFn = ({ initialState } = {}) =>
new ApolloClient({
uri: 'https://mysite.com/graphql',
cache: new InMemoryCache().restore(initialState || {}),
});
export default withApollo(clientFn, {
render: ({ Page, props }) => {
return (
<ApolloProvider client={props.apollo}>
<Page {...props} />
</ApolloProvider>
);
},
});
// pages/index.js
import gql from 'graphql-tag';
import { useQuery } from '@apollo/react-hooks';
import withApollo, { clientFn } from '../lib/withApollo';
const QUERY = gql`
{
title
}
`;
const Index = () => {
const { loading, data } = useQuery(QUERY);
if (loading || !data) {
return <h1>loading...</h1>;
}
return <h1>{data.title}</h1>;
};
export const getServerSideProps = async () => {
const apolloClient = clientFn();
// apolloClient.* https://www.apollographql.com/docs/react/api/apollo-client/#apolloclient-functions
// You do not use hooks like useQuery, useMutation in here
return {
props: {
apollo: apolloClient,
apolloState: {
data: apolloClient.cache.extract(),
},
},
};
};
export default withApollo(Index);
@hoangvvo You're not wrong, hence why we haven't updated the Apollo examples in the Next.js repo, but that surely will change with time, in the mean time is okay to use getInitialProps, it's not going anywhere
@lfades , have you tried using the beta version of the @apollo/client with nextjs 9.3+?
I haven't, is there something new that requires an update?
I still don't like the size of their package, keeps getting bigger: https://bundlephobia.com/result?p=@apollo/[email protected] :fearful:
I just tried it with Next 9.3 and it seems to work. I do see loading state for some of my content when I view source though - unsure if that is related?
@wesbos going to try Next 9.3.5 / TS with this package.
@wesbos SSR is now disabled by default unless you manually enable it by importing and adding getDataFromTree to the options:
export default withApollo(Index, { getDataFromTree });
Why are you disabling it by default?
And does this lib mirror the official with-apollo next.js example? I'm using that example but I think I should just get rid of it and use this lib.
Thanks!
@samuelcastro Feel free to use that example of this lib, you can't go wrong with either (I also helped trying to keep that example updated).
SSR is disabled by default because static pages are faster, better overall, and more reliable, and can also be dynamic when you take advantage of SSG, it just happens that it's harder to do with the current state of the Apollo library. But that surely will be improved in the future.
@lfades i've read: https://github.com/zeit/next.js/discussions/10930#discussioncomment-5525
Is this a reason for not switching this library (next-with-apollo) to getServerSideProps?
@webcoderkz Not really, getServerSideProps is better in the way that it's never executed in the client, so it's only included for the server bundle.
The reason I haven't migrated the library yet is because getInitialProps is a static method inside the page, and you can more easily add an Apollo HOC on top of your pages, If I change it to work with getStaticProps it would take additional steps to get the setup working.
This question kind of extends beyond just the use of this library or Apollo, but I'm curious to know: is there a 'best practice' way to do what @juanpablocs mentioned above for dynamically returning a status code from the server using Apollo? I want to return an appropriate status code from the server based on what exists in a CMS and could just use fetch, but I would like to keep Apollo in some places in order to fetchMore on the frontend. Any advice would be greatly appreciated, and apologies if this isn't the right place for this.
After a few hours trying to make this work with @apollo/[email protected], I can see that the actual implementation and examples are kind of working, with next-with-apollo, the request is made on the client event if the data is hydrated, showing a loading state (as @wesbos stated before) (I'm using getDataFromTree), I tested both app and per page HOC. With the example from the next.js page with apollo, it works but I have to explicitly set the ssrMode: true on both server and client (the Boolean(ctx) trick is not working), in order to not make the request again in the client, even with the hydrated data.
@CharlieDieter Why do you need to return a status code from the server to the client? what value is that providing for cases where it's not an error?
Overall I would like to just completely change the implementation of Apollo in the Next.js examples as it keeps breaking constantly for some reason :cry:
In my case, I have a CMS backend where content creators can build pages with a pathname. So if you go to /example, the page at /pages/[uid].js will make a graphql request for a document with uid: example. That's fine, but then if you go to /asdfasdf and no page is found by uid: asdfsdf in the CMS, the CMS will return an error and that should return a 404 not found error to the client. Another possible example of wanting to change the status code could be to do a 301 or 302 redirect.
I just tried it with Next 9.3 and it seems to work. I do see loading state for some of my content when I view source though - unsure if that is related?
Looks like it is related. I'm having the same issue. When viewing source I see the loading state.
I'm trying to make getServerSideProps work with apollo with the following code(based on @hoangvvo 's suggestion)
Type Props = user
const UserProfilePage: React.FunctionComponent<Props> = (props) => {
const router = useRouter()
// this is for CSR
const { data, loading, error } = useQuery(USER_QUERY, {
variables: { userName: router.query.userId },
})
if (error) {
return (
<Layout title="Something">
<div className="mt-4">
<PageLoading />
</div>
</Layout>
)
}
if (loading) {
const user: User = props
return (
<Layout
title={`Something`}
description={`${user ? user.about : ''}'s profile`}
>
{user && <UserDetail user={user} />}
</Layout>
)
}
if (data) {
const user: User = data.user
return (
<Layout
title={`${user ? user.name : ''}'s profile`}
description={`${user ? user.about : ''}`}
>
{user && <UserDetail user={user} />}
</Layout>
)
}
return null
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const apolloClient = clientFn()
// this is for SSR
const response = await apolloClient.query({
query: USER_QUERY,
variables: { userName: context.params?.userId },
})
const userFromServer = response.data.user
return { props: userFromServer }
}
export default UserProfilePage
This worked for me. Just in case if anyone is looking.
@SoorajChandran Isn't this a different implementation from @hoangvvo's proposed one that passes client and apolloState, since it passes the value obtained by SSR directly as props?
@SoorajChandran hi i use graphql-code-generator do you known how to generate this code to typescript code ?
const response = await apolloClient.query({
query: USER_QUERY,
variables: { userName: context.params?.userId },
})
i want to query, variables type checking
I'm currently evaluating the options to move from getInitialProps to either full getStaticProps(SSG) or a hybrid and based on what I've read in this thread it doesn't seem to be needed? I'm currently setting up the apollo client and then using it in pages to query the data at build time for full SSG and it seems to work, but i'm not able to use cached queries - posted a discussion here if you're interested @lfades :
https://github.com/vercel/next.js/discussions/14471