-
Notifications
You must be signed in to change notification settings - Fork 7
Conversation
* Remove deprecated `@types/next` * Add `next@9.1.7` to devDependencies * Replace `NextComponentClass` | `NextFC` union describing `Page` with `NextPage` * Rename `NextContextWithAppTree` to `NextUrqlContext` * Make `NextUrqlContext` extend `NextPageContext` instead of `NextContext`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some comments to hopefully clarify my train of thought
__tests__/with-urql-client.spec.tsx
Outdated
@@ -98,7 +96,7 @@ describe('withUrqlClient', () => { | |||
Component = withUrqlClient(ctx => ({ | |||
url: 'http://localhost:3000', | |||
fetchOptions: { | |||
headers: { Authorization: ctx.req.headers.cookie }, | |||
headers: { Authorization: ctx.req ? ctx.req.headers.cookie : null }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TS was complaining that req
could be undefined here... which I thought was weird because that's not anything new. The previous context had an optional req
property on it, but TS wasn't complaining then 🤔 Will take another look tomorrow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't worry too much about it. This is the accurate type now, and actually should be what users use. For the first server-rendered result, ctx.req
will be defined, but on subsequent client-side navigation you'll never actually get a req
object, b/c no request was made to the server. This looks good to me ✅
@@ -18,24 +18,21 @@ interface PageProps { | |||
pageProps?: WithUrqlClient; | |||
} | |||
|
|||
export interface NextContextWithAppTree extends NextContext { | |||
AppTree: React.ComponentType<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need AppTree
anymore, it's included on NextPageContext
now
|
||
declare const withUrqlClient: <T = any, IP = any>( | ||
clientOptions: NextUrqlClientConfig, | ||
clientConfig: NextUrqlClientConfig, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with parameter name in implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:chefs-kiss:
Page: | ||
| NextComponentClass<T & IP & WithUrqlClient, IP> | ||
| NextFC<T & IP & WithUrqlClient, IP>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consolidate into NextPage
) => NextFC< | ||
T & IP & WithUrqlClient & WithUrqlInitialProps & PageProps, | ||
Page: NextPage<T & IP & WithUrqlClient, IP>, | ||
) => NextComponentType< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update NextFC
to NextComponentType
, who's type variables are in the reverse order of NextFC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love when generic order gets changed around like that :oof:
@@ -29,14 +29,13 @@ interface PageProps { | |||
pageProps?: WithUrqlClient; | |||
} | |||
|
|||
export interface NextContextWithAppTree extends NextContext { | |||
AppTree: React.ComponentType<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need AppTree
anymore, it's included on NextPageContext
now
Page: | ||
| NextComponentClass<T & IP & WithUrqlClient, IP> | ||
| NextFC<T & IP & WithUrqlClient, IP>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consolidate into NextPage
const withUrql: NextFC< | ||
T & IP & WithUrqlClient & WithUrqlInitialProps & PageProps, | ||
return (Page: NextPage<T & IP & WithUrqlClient, IP>) => { | ||
const withUrql: NextComponentType< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update NextFC
to NextComponentType
, who's type variables are in the reverse order of NextFC
__tests__/with-urql-client.spec.tsx
Outdated
@@ -1,12 +1,10 @@ | |||
import React from 'react'; | |||
import { shallow, configure } from 'enzyme'; | |||
import Adapter from 'enzyme-adapter-react-16'; | |||
import { NextFC } from 'next'; | |||
import { NextComponentType } from 'next/types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be able to just import
this directly from next
. They should be moving their types to a top-level lib export:
import { NextComponentType } from 'next/types'; | |
import { NextComponentType } from 'next'; |
|
||
// Fake up a string to simulate, say, a token accessed via browser cookies or localStorage. | ||
const token = Math.random() | ||
.toString(36) | ||
.slice(-10); | ||
|
||
const mockContext: NextContextWithAppTree = { | ||
const mockContext: NextUrqlContext = { | ||
AppTree: MockAppTree, | ||
pathname: '/', | ||
query: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI I'm also seeing a TS error on L87 (in the new diff):
Type '{ headers: { cookie: string; }; }' is missing the following properties from type 'IncomingMessage': httpVersion, httpVersionMajor, httpVersionMinor, complete, and 40 more.
We'll just have to coerce the req
type like so:
req: {
headers: {
cookie: token,
},
} as NextUrqlContext['req']
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh cool, didn't know about accessing a type property like that!
src/with-urql-client.tsx
Outdated
@@ -1,5 +1,5 @@ | |||
import React from 'react'; | |||
import { NextComponentClass, NextFC, NextContext } from 'next'; | |||
import { NextPage, NextPageContext, NextComponentType } from 'next/types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to just import
ing from next
directly.
src/with-urql-client.tsx
Outdated
@@ -77,7 +72,7 @@ function withUrqlClient<T = any, IP = any>( | |||
); | |||
}; | |||
|
|||
withUrql.getInitialProps = async (ctx: NextContextWithAppTree) => { | |||
withUrql.getInitialProps = async (ctx: NextUrqlContext) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think this type should actually be just:
withUrql.getInitialProps = async (ctx: NextUrqlContext) => { | |
withUrql.getInitialProps = async (ctx: NextPageContext) => { |
the reason being that, at this point in the function's execution, we can't safely access ctx.urqlClient
b/c it doesn't exist yet (it gets added on L83).
Ofc, that'll result in a type error, so on L83 you'll need to do:
(ctx as NextUrqlContext).urqlClient = urqlClient;
It's a small thing, but I think it better signals to future readers what we're doing here, which is actually shoving a property onto the original ctx
object so that components lower in the tree can access it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh I see, makes sense. Would it also be helpful to coerce ctx
as NextUrqlContext
when we pass it to Page.getInitialProps
on L89?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yep, good catch – that way if a user wants to access ctx.urqlClient
in their own getInitialProps
function they can. Let's do that, and then I'll merge this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, and I figure it's at least more accurate! Added that in 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking real good to me @ryan-gilb! Left some small suggestions in there – once we get those in I'll hit the ✅
Thanks for the feedback @parkerziegler 🙌 I implemented your suggestions and added some more coercion to Also left a question expanding on signaling intent to readers, let me know your thoughts! ❤️ |
Woohoo! Merge ahoy! |
Edit: Fixed the type issue in setting up the test component in
with-urql-client.spec.ts
Summary
Next 9 was recently released and has first-class TS types! None of the types we were previously using (
NextContext
,NextComponentClass
,NextFC
) exist in the same way this version, so I had to look at what's available and figure out a (hopefully) reasonable mapping. I tested this upgrade with the first example and it worked fine -- things started to fall apart when running the tests. Going to revisit this tomorrow with fresh eyes! For now, here's what I came up with:NextContext
NextPageContext
, includesAppTree
, and is no longer generalizedNextContextWithAppTree
toNextUrqlContext
and extendNextPageContext
, allowing us to removeAppTree
NextComponentClass
,NextFC
NextComponentType
, a generalized intersection overReact.ComponentType
andgetInitialProps
, accepting type variables for context, initialProps, and props (in that order).NextFC
in tests withNextComponentType
withUrqlClient
, replaced union overNextComponentClass
andNextFC
withNextPage
; seemed to make sense given the parameter name isPage
withUrql
toNextComponentType
; had to switch order of type variables from<P, IP, C>
to<C, IP, P>
Context
#20
Notes
The
yarn.lock
diff is HUGE. What's the process here? Add everything, or only the related package changes?