When combining Next + Redux + urql in certain manner looks like suspense(such as returning different view depending on redux store value with useSelector (redux hooks)), server runs as if code asserted Suspense.
If I use useState instead of useSelector, then everything works fine.
I spent some time looking over the source code of next-urql, https://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/with-urql-client.tsx @ line 93, initUrqlClient includes hardcoded parameter for Suspense usage as below.
const urqlClient = initUrqlClient(clientConfig, true);
Would there be any chance of fixing this bug? It would be nice to handle this with parameter or function.
* Guess this might be related to https://github.com/FormidableLabs/urql/issues/916 *
urql version & exchanges:
Steps to reproduce
Take a look at the below codeSandbox
https://codesandbox.io/s/hardcore-mcnulty-1c1vv
Expected behavior
Suspense must not run in Server Side render
Actual behavior
Guessing Suspense-like code runs in server preventing server to render properly
The main reasoning behind that hardcoded truthy value there is to let the init know we can or can't bind suspense since this only has to be active when options.ssr is true or we have getInitialProps (we use this for ssr-prepass).
As you can see this truthy value does not imply a 100% guarantee of suspense https://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/init-urql-client.ts#L17 since we prepass here all boundaries should have been resolved resulting in no suspense behavior on the server.
The error in #916 seems similar in the essence that this check does not correctly work when using with _app rather than on page/component level. I'll look into this
This issue occurs when the useQuery runs after ssr-prepass.
Due to the use of redux, the server will be rendered twice.
ssr-prepass handles suspence, but it does not work after ssr-prepass has been used.
If the useQuery is run for the first time after ssr-prepass on the server, a separate action seems necessary.
I've dug deeper into both this and the other issue concerning getServerSideprops and reached the conclusion that this case is going to be really hard/impossible to support given the current API.
Formerly we only had getInitialProps which would be available on the component, so we could detect the presence of this and use where/when needed. Now with getStaticProps being a function that we export from the file we can't effectively couple these. This means when we run our prepass function to resolve our queries we won't have these injected props they'll be undefined.
This means that we execute our query with undefined, after that next.js will execute renderToString and use these functions to inject additional props. Now all of a sudden we'll see new variables on useQuery making it execute again, however we are in a regular renderToString meaning that because this new query dispatches and throws a Suspense boundary the server crashes.
For this to work the data-derivation from the component-tree should be a first-class citizen with access to the props injected with these functions.
Another solution would be to add an option to fully opt out of Suspense this would also mean that the queries that we derive from our prepass aren't in line with the ones you want on screen and there won't be server-side data fetching with the useQuery calls.
/CC @timneutkens
Most helpful comment
The main reasoning behind that hardcoded
truthyvalue there is to let theinitknow we can or can't bindsuspensesince this only has to be active whenoptions.ssris true or we havegetInitialProps(we use this forssr-prepass).As you can see this
truthyvalue does not imply a 100% guarantee ofsuspensehttps://github.com/FormidableLabs/urql/blob/main/packages/next-urql/src/init-urql-client.ts#L17 since we prepass here all boundaries should have been resolved resulting in no suspense behavior on the server.The error in #916 seems similar in the essence that this check does not correctly work when using with
_apprather than on page/component level. I'll look into this