Deleting an abstraction we built ourselves, and writing down what replaces it.
This is a pull request I opened at InterNations. It is laid out below the way my colleagues would have come across it: as a review page, at the point where they had to decide whether to take the change on.
The description is the part on display here. The diff that went with it is private, and links to the repository and to our internal tools are flattened to plain text, so nothing below will take you somewhere it shouldn’t.
Remove Realms and Pages Router#10001
Mergedpatik merged this pull request after 3 reviews
ℹ️ This PR is huge. Too big, even. We can review it together on Tuesday 2 June in the Dojo. Until then, you can check out the description.
Description
Pour one out for realms 🪦
And no more Pages Router—all of our screens are now in App Router 🎉
Tip
Deployed to an internal staging deployment
1. Router hooks
1.1 useINRouter deprecated
See next section about what to use instead.
1.2 When to use useINAppRouter vs Next’s usePathname and useSearchParams
useINAppRouter combines the return values of useRouter, usePathname, and useSearchParams with our own go() function. It also served as
However, if any of the Next hooks have an internal change, useINAppRouter will trigger a re-render of the component. In many cases this is not be necessary or desirable.
If your component only needs pathname and/or searchParams, it’s now preferable to use usePathname and useSearchParams instead. That way your component will only re-render if the pathname or searchParams change.
What if we need pathname and go (or push or replace)?
const { go, pathname } = useINAppRouter()
In this case you might as well leave it like that. useINAppRouter will trigger a re-render for changes to pathname anyway, even if you are getting pathname from usePathname. So calling one hook is probably better than calling two.
I’m considering removing pathname and searchParams from useINAppRouter. What do you think?
1.3 Return type changes
In the past, Next’s hooks could return null:
pathname: string |null
searchParams: ReadonlyURLSearchParams |null
This led us to putting lots of little truthy checks and optional chains in our code:
constthing1= pathname && pathname.includes('...') ? foo : bar
constthing2= searchParams?.get('foo')
The hooks no longer return null. I’ve updated useINAppRouter to reflect this. I also cleaned up a bunch of those truthy checks throughout our codebase.
Although this information is true, we sadly cannot make use of it yet. When you run yarn build, Next adds the CompatRouter types to its generated type file. This makes the IDE linter complain that the values may be null. Even though the docs say this shouldn’t happen without Pages Router in the picture, better safe than sorry.
3. Tests
3.1. Deprecated appRouter: true
Now, all tests are wrapped in the App Router root layout and providers.
Tip
Most changes in this PR are just removing this option.
3.2. render() no longer supports the realm option
render(..., { realm: '...' }) is no longer possible
If you’re testing a component that can be run anywhere, this option can be safely dropped.
If the test only runs within one route group, either pass the route group’s layout using the wrapper option, or use usePathnameMock.mockReturnValue() if you need to set the URL.
3.3. render() no longer supports the router option
i.e. for setting the URL. Instead, continue using usePathnameMock.mockReturnValue().
3.4. Unskipped all skipped tests
I revisited all of the tests using test.skip and fixed them. Except for one, in frontend/tracking/usePageViewsTracking.test.tsx, which doesn’t seem to work properly on the CI, but will now run locally.
4. Removed *-Legacy components and hooks
e.g. dialog and paywall providers, many others. We named them with *Legacy to denote which ones were meant for Pages Router. Replacement components were already in use (i.e. instead of FooLegacy, use Foo).
5. Realm checks
5.1 Removed checks for Checkout realm
e.g. isCheckout(). We shouldn’t need this anymore for 99% of cases because our code should be structured in a way that we can avoid it.
Note
Exception: frontend/data/api/api.ts
5.2 Removed many checks for MandatoryRegistration realm
e.g. isMandatoryRegistration(). We shouldn’t need this anymore for 90% of cases because our code should be structured in a way that we can avoid it. Please only use it as a last resort.