Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Add usePageSwitcherPagination hook#44664

Merged
philipp-spiess merged 15 commits into
mainfrom
ps/use-paginated-connection
Dec 6, 2022
Merged

Add usePageSwitcherPagination hook#44664
philipp-spiess merged 15 commits into
mainfrom
ps/use-paginated-connection

Conversation

@philipp-spiess

@philipp-spiess philipp-spiess commented Nov 21, 2022

Copy link
Copy Markdown
Contributor

Part of #44706

This PR is part of the strategic readiness effort to improve pagination.

We're adding new primitives to help us build more-robust and proper cursor-based bi-directional pagination. This PR adds a new hook, usePageSwitcherPagination which is a fork of useConnection with a few changes:

  1. It requires a bi-directional connection (one that can be traversed forwards and backwards).
  2. It support syncing the page state to the URL (like useConnection does).
  3. It does not support custom filter or sort orders yet. However, the new hook is designed in a way where we will be able to do this easily and more reliably than useConnection.
  4. It does not support periodic refreshment (polling). If this is needed, I suggest we export a refresh/reload function and implement this logic outside of this hook.
  5. It has slightly different type-requirements. Specifically the new usePageSwitcherPagination hook requires you to give up all pagination related props to the hook. You can only manage initial page sizes but every subsequent page change is controller for you. This way we avoid the confusion when users have to pass first: and after: manually right now with the existing useConnection hook, even though it's thrown away after the first page load (and sometimes not even used at all if e.g. state from the URL is restored).

Everything is designed with the new pagination controls in mind which I'll be adding in a new PR:

Screenshot 2022-11-21 at 16 48 06

Notes

  • This PR will have a failing CI until we add the backend support and at least one GraphQL resource that eposes the backward-pagination properties. This means that merging this PR is currently blocked.

Test plan

Added unit tests to test all of the new features. I've also tested it agains the WIP PR #44347

App preview:

Check out the client app preview documentation to learn more.

@cla-bot cla-bot Bot added the cla-signed label Nov 21, 2022
@github-actions github-actions Bot added the team/code-exploration Issues owned by the Code Exploration team label Nov 21, 2022
@philipp-spiess philipp-spiess self-assigned this Nov 21, 2022
@philipp-spiess philipp-spiess marked this pull request as ready for review November 21, 2022 15:52
@philipp-spiess philipp-spiess marked this pull request as draft November 21, 2022 15:53
@philipp-spiess philipp-spiess changed the title Add usePaginatedConnection hook Add usePageSwitcherPagination hook Nov 22, 2022
@philipp-spiess philipp-spiess requested review from a team, 0xnmn and courier-new November 23, 2022 15:35
@philipp-spiess philipp-spiess marked this pull request as ready for review November 23, 2022 15:35
Comment thread client/web/src/components/FilteredConnection/hooks/usePageSwitcherPagination.ts Outdated
Comment thread client/web/src/components/FilteredConnection/hooks/usePageSwitcherPagination.ts Outdated
Comment thread client/web/src/components/FilteredConnection/hooks/usePageSwitcherPagination.ts Outdated
Comment on lines 194 to 161

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can search contain before and after values with are not valid paginated connection query arguments (e.g., '?before=john&after=doe')? If yes, should we validate these values before using them in query?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tokens are opaque so we can't do any form of validation (the backend will do that when we query it, though).

And no, before and after at the same time is not allowed. That's why i made it so there's only a after or a before branch. We never set both arguments at the same time (after takes presedenc but it doesn't really matter)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@philipp-spiess @taras-yemets this might be super obvious but I just recently noticed that this is a valid URL if you have more than one value of the same query param, for example

var s = new URLSearchParams('?site=x&site=y')
s.getAll('site') // ["x", "y"]

this is of course a corner case but I think Taras may be right here, what if we have another consumer on the page that uses the same query params. Should we add console.warn if we find more than one pagination-like query param?

Super minor, feel free to ignore.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add console.warn if we find more than one pagination-like query param?

I’m not sure how we could detect this scenario though. When we load the hook and detect pagination-like query params, we currently assume it is from the current pagination (there's nothing to identify it with, unfortunately).

FWIW this behavior has been a part of the existing pagination related abstractions as well (the legacy class component as well as the old useConnection hook).

@philipp-spiess

Copy link
Copy Markdown
Contributor Author

This PR is currently blocked by the backend changes that @thenamankumar is working on because it uses a real GraphQL query in the tests that doesn't have the after and last fields implemented yet 😅

@philipp-spiess philipp-spiess force-pushed the ps/use-paginated-connection branch from b2a82ac to b77450c Compare December 2, 2022 15:21

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to have a default page size at backend? Given the args are naturally not null.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now its 100 which is same as the max page size allowed. Shall we have a separate default page size? 20?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think at the backend if no first or after is set, we should error. WDYT?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Checked github api. That is what they do too. So yeah I'll add err in the backend.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this. Having the url sync part of the connect hook, makes everything so simple and smooth.

@0xnmn

0xnmn commented Dec 5, 2022

Copy link
Copy Markdown
Contributor

Not approving because the BE PR is not merged yet. Otherwise LGTM.

@valerybugakov valerybugakov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff, @philipp-spiess!

Comment on lines 109 to 112

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the Apollo Client documentation, it seems that refetch() calls use each omitted variable's original value. Would it be possible to remove the logic related to initialQueryVariables to simplify the hook?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh that's nice, ty!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beautiful tests! 🔥

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

Comment on lines 82 to 84

@valerybugakov valerybugakov Dec 6, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to useMemo initialQueryVariables if we don't use it in the updatePagination function? I thought that it would be nice to remove it if this is possible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@valerybugakov I wasn't sure, I need to do more research. I was worried that a new variables object passed on every re-render with the previous pagination values might cause some headache and I only want it to reset when the user-supplied variables change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@philipp-spiess I think the last time I checked useQuery hook used this package for deep variable and query options comparing https://github.com/benjamn/wryware/blob/main/packages/equality/src/equality.ts

Feel free to leave this useMemo call here this is more like FYI.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vovakulikov Thanks! I removed it for now as I'd rather add it when I know it's necessary.

@philipp-spiess philipp-spiess force-pushed the ps/use-paginated-connection branch from cad93b8 to 63d39ab Compare December 6, 2022 14:33
@philipp-spiess

Copy link
Copy Markdown
Contributor Author

I removed the dependence on a GraphQL schema that implements both forward and backward navigation (stubbed out the types) so we can ship this independently. Will update the types to run against the real schema once we have migrated at least one connection.

@sg-e2e-regression-test-bob

sg-e2e-regression-test-bob commented Dec 6, 2022

Copy link
Copy Markdown

Bundle size report 📦

Initial size Total size Async size Modules
0.00% (0.00 kb) 0.00% (0.00 kb) 0.00% (0.00 kb) 0.00% (0)

Look at the Statoscope report for a full comparison between the commits a68593b and daeedc4 or learn more.

Open explanation
  • Initial size is the size of the initial bundle (the one that is loaded when you open the page)
  • Total size is the size of the initial bundle + all the async loaded chunks
  • Async size is the size of all the async loaded chunks
  • Modules is the number of modules in the initial bundle

@philipp-spiess philipp-spiess merged commit 66a455a into main Dec 6, 2022
@philipp-spiess philipp-spiess deleted the ps/use-paginated-connection branch December 6, 2022 15:39
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants