Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

(next-urql) - Never suspend option (#923)

* add option to disable suspense

* add changeset

* add docs

* correct the brackets for 'shouldEnableSuspense'

* Apply suggestions from code review

authored by

Jovi De Croock and committed by
GitHub
1a439fd2 e55f2751

+71 -7
+5
.changeset/chatty-poems-film.md
··· 1 + --- 2 + 'next-urql': minor 3 + --- 4 + 5 + Add option called `neverSuspend` to disable `React.Suspense` on next.js.
+5
docs/advanced/server-side-rendering.md
··· 241 241 Unless the component that is being wrapped already has a `getInitialProps` method, `next-urql` won't add its own SSR logic, which automatically fetches queries during 242 242 server-side rendering. This can be explicitly enabled by passing the `{ ssr: true }` option as a second argument to `withUrqlClient`. 243 243 244 + When you are using `getStaticProps`, `getServerSideProps`, or `getStaticPaths`, you should opt-out of `Suspense` by setting the `neverSuspend` option to `true` in your `withUrqlClient` configuration. 245 + your `withUrqlClient`. 246 + During the prepass of your component tree `next-urql` can't know how these functions will alter the props passed to your page component. This injection 247 + could change the `variables` used in your `useQuery`. This will lead to error being thrown during the subsequent `toString` pass, which isn't supported in React 16. 248 + 244 249 ### Resetting the client instance 245 250 246 251 In rare scenario's you possibly will have to reset the client instance (reset all cache, ...), this is an uncommon scenario
+5
packages/next-urql/README.md
··· 246 246 component has children using `getInitialProps` but that component itself is not and you want to opt in to this behavior you'll have to set the second argument of 247 247 `withUrqlClient`, this means `withUrqlClient(() => clientOptiosn, { ssr:true })`. 248 248 This measure is available so we can support `getStaticProps`, ... 249 + 250 + When you are using `getStaticProps`, `getServerSideProps`, or `getStaticPaths`, you should opt-out of `Suspense` by setting the `neverSuspend` option to `true` in your `withUrqlClient` configuration. 251 + your `withUrqlClient`. 252 + During the prepass of your component tree `next-urql` can't know how these functions will alter the props passed to your page component. This injection 253 + could change the `variables` used in your `useQuery`. This will lead to error being thrown during the subsequent `toString` pass, which isn't supported in React 16.
+46
packages/next-urql/src/__tests__/with-urql-client.spec.tsx
··· 162 162 expect(exchange).toBeCalledTimes(1); 163 163 }); 164 164 }); 165 + 166 + describe('never-suspend', () => { 167 + // Simulate a token that might be passed in a request to the server-rendered application. 168 + const token = Math.random().toString(36).slice(-10); 169 + let mockSsrExchange; 170 + 171 + const mockContext: NextUrqlPageContext = { 172 + AppTree: MockAppTree, 173 + pathname: '/', 174 + query: {}, 175 + asPath: '/', 176 + req: { 177 + headers: { 178 + cookie: token, 179 + }, 180 + } as NextUrqlPageContext['req'], 181 + urqlClient: {} as Client, 182 + }; 183 + 184 + beforeEach(() => { 185 + Component = withUrqlClient( 186 + (ssrExchange, ctx) => ({ 187 + url: 'http://localhost:3000', 188 + fetchOptions: { 189 + headers: { Authorization: (ctx && ctx.req!.headers!.cookie) || '' }, 190 + }, 191 + exchanges: [(mockSsrExchange = ssrExchange)], 192 + }), 193 + { ssr: true, neverSuspend: true } 194 + )(MockApp); 195 + }); 196 + 197 + it('should not enable suspense', async () => { 198 + Component.getInitialProps && 199 + (await Component.getInitialProps(mockContext)); 200 + 201 + expect(spyInitUrqlClient).toHaveBeenCalledWith( 202 + { 203 + url: 'http://localhost:3000', 204 + fetchOptions: { headers: { Authorization: token } }, 205 + exchanges: [mockSsrExchange], 206 + }, 207 + false 208 + ); 209 + }); 210 + }); 165 211 });
+1
packages/next-urql/src/types.ts
··· 51 51 52 52 export interface WithUrqlClientOptions { 53 53 ssr?: boolean; 54 + neverSuspend?: boolean; 54 55 }
+9 -7
packages/next-urql/src/with-urql-client.tsx
··· 29 29 options?: WithUrqlClientOptions 30 30 ) { 31 31 if (!options) options = {}; 32 + 32 33 return (AppOrPage: NextPage<any> | typeof NextApp) => { 33 - const shouldBindGetInitialprops = Boolean( 34 - AppOrPage.getInitialProps || options!.ssr 34 + const shouldEnableSuspense = Boolean( 35 + (AppOrPage.getInitialProps || options!.ssr) && !options!.neverSuspend 35 36 ); 36 37 37 38 const withUrql = ({ urqlClient, urqlState, ...rest }: WithUrqlProps) => { ··· 59 60 } 60 61 61 62 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion 62 - return initUrqlClient(clientConfig, shouldBindGetInitialprops)!; 63 - // eslint-disable-next-line react-hooks/exhaustive-deps 63 + return initUrqlClient(clientConfig, shouldEnableSuspense)!; 64 64 }, [urqlClient, urqlState, forceUpdate[0]]); 65 65 66 66 const resetUrqlClient = () => { ··· 83 83 // Set the displayName to indicate use of withUrqlClient. 84 84 withUrql.displayName = `withUrqlClient(${getDisplayName(AppOrPage)})`; 85 85 86 - if (shouldBindGetInitialprops) { 86 + if (AppOrPage.getInitialProps || options!.ssr) { 87 87 withUrql.getInitialProps = async (appOrPageCtx: NextUrqlContext) => { 88 88 const { AppTree } = appOrPageCtx; 89 89 ··· 104 104 fetchExchange, 105 105 ]; 106 106 } 107 - const urqlClient = initUrqlClient(clientConfig, true); 107 + 108 + const urqlClient = initUrqlClient(clientConfig, !options!.neverSuspend); 108 109 109 110 if (urqlClient) { 110 111 (ctx as NextUrqlContext).urqlClient = urqlClient; ··· 127 128 const appTreeProps = isApp ? props : { pageProps: props }; 128 129 129 130 // Run the prepass step on AppTree. This will run all urql queries on the server. 130 - await ssrPrepass(<AppTree {...appTreeProps} />); 131 + if (!options!.neverSuspend) 132 + await ssrPrepass(<AppTree {...appTreeProps} />); 131 133 132 134 return { 133 135 ...pageProps,