Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request: Support next.js 9.3 #114

Open
LassiterJ opened this issue Mar 11, 2020 · 26 comments
Open

Request: Support next.js 9.3 #114

LassiterJ opened this issue Mar 11, 2020 · 26 comments

Comments

@LassiterJ
Copy link

Would like an update for the new version of next.js. Specifically including the new data-fetching methods and examples of use.

@lfades
Copy link
Owner

lfades commented Mar 11, 2020

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.

@LassiterJ
Copy link
Author

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.

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!

@lfades
Copy link
Owner

lfades commented Mar 12, 2020

@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.

@juanpablocs
Copy link

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;
  }
 ...
};

@hoangvvo
Copy link
Contributor

hoangvvo commented Apr 4, 2020

@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.

@hoangvvo
Copy link
Contributor

hoangvvo commented Apr 4, 2020

I imagine it would be difficult to make next-with-apollo to work with getServerSideProps because getServerSideProps is completely separated from the React component.

  • AppTree is not available. ssr is impossible.
  • no way to connect getServerSideProps to the the component (to restore cache / apolloState, apollo props).

Correct me if I am wrong @lfades

@hoangvvo
Copy link
Contributor

hoangvvo commented Apr 4, 2020

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);

@lfades
Copy link
Owner

lfades commented Apr 8, 2020

@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

@vmptk
Copy link

vmptk commented Apr 22, 2020

@lfades , have you tried using the beta version of the @apollo/client with nextjs 9.3+?

@lfades
Copy link
Owner

lfades commented Apr 22, 2020

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/client@3.0.0-beta.44 😨

@wesbos
Copy link
Contributor

wesbos commented Apr 23, 2020

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?

@avxkim
Copy link

avxkim commented Apr 24, 2020

@wesbos going to try Next 9.3.5 / TS with this package.

@lfades
Copy link
Owner

lfades commented Apr 24, 2020

@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 });

@samuelcastro
Copy link

samuelcastro commented Apr 25, 2020

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!

@lfades
Copy link
Owner

lfades commented Apr 25, 2020

@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.

@avxkim
Copy link

avxkim commented Apr 25, 2020

@lfades i've read: vercel/next.js#10930 (comment)
Is this a reason for not switching this library (next-with-apollo) to getServerSideProps?

@lfades
Copy link
Owner

lfades commented Apr 26, 2020

@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.

@charliedieter
Copy link

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.

@batusai513
Copy link

batusai513 commented Apr 28, 2020

After a few hours trying to make this work with @apollo/client@3.0.0-beta.44, 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.

@lfades
Copy link
Owner

lfades commented Apr 29, 2020

@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 😢

@charliedieter
Copy link

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.

@SoorajChandran
Copy link

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.

@SoorajChandran
Copy link

SoorajChandran commented Apr 30, 2020

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.

@km-tr
Copy link

km-tr commented May 7, 2020

@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?

akarlsten added a commit to akarlsten/Fora that referenced this issue Jun 2, 2020
@ITSWYoo
Copy link

ITSWYoo commented Jun 16, 2020

@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

@aamorozov
Copy link

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 :
vercel/next.js#14471

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests