urql-graphql / urql

The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
https://urql.dev/goto/docs
MIT License
8.54k stars 444 forks source link

Non RSC authExchange failing #3525

Closed Nohac closed 3 months ago

Nohac commented 4 months ago

Describe the bug

I've followed the steps for nextjs appdir. I've added authExchange to the non RSC setup, and in addAuthToOperation I'm fetching access token from the server using nextjs server action. When I do this, I'm getting the following errors/warnings:

Warning: Can't perform a React state update on a component that hasn't mounted yet. This indicates that you have a side-effect in your render function that asynchronously later calls tries to update the component. Move this work to useEffect instead.
Router@webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:90:130
ErrorBoundaryHandler@webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:62:9
ErrorBoundary@webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:87:56
AppRouter@webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:374:48
ServerRoot@webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:154:25
RSCComponent
Root@webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:171:25 [app-index.js:32:21](webpack://_N_E/node_modules/next/dist/client/app-index.js?d705)
authExchange()’s initialization function has failed, which is unexpected.
If your initialization function is expected to throw/reject, catch this error and handle it explicitly.
Unless this error is handled it’ll be passed onto any `OperationResult` instantly and authExchange() will block further operations and retry. Error: Connection closed.

Reproduction

https://stackblitz.com/edit/github-1sqstp?file=app%2Fnon-rsc%2Flayout.tsx

Urql version

urql 4.0.6

Validations

JoviDeCroock commented 3 months ago

I don't think you should be able to call server-actions from non-DOM interactions 😅 as what seems to basically be happening is that the connection is closed immediately. It also tries to tell you this

Warning: Can't perform a React state update on a component that hasn't mounted yet. This indicates that you have a side-effect in your render function that asynchronously later calls tries to update the component. Move this work to useEffect instead.

As the server-action will try to update state on a component that doesn't exist yet. We'd probably also have to catch the action into a loading state, not sure whether server-actions are subject to Suspense but if they are then in this case it happens outside of a component and it might be hard for React to figure out where this belongs.

Nohac commented 3 months ago

You're right. I was following this guide and it looked like I could use server actions like a normal async function.

Moving from action to a normal api for subsequent fetches, and passing the token from RSC to the provider on initial render made the issues go away.