GraphQL Client: Add `useConnection` hook to replace `<FilteredConnection />`
Created by: umpox
Context
To successfully migrate to using Apollo and React hooks for data fetching, we need to consider FilteredConnection
This is, by far, the largest and most complex single component we have right now. It is integral to data-fetching across the application so it is important that we replace this component with an alternative that will allow us to effectively use Apollo and improve our data fetching.
Previous attempt
Prior to this, I tried to achieve interoperability between requestGraphQL
and client.watchQuery
by converting Apollos zen-observable
to RxJS
compatible ones. This is effectively the same as what apollo-angular does. However there are numerous issues with this, (e.g. various operators that we use in RxJS
still aren't supported). There are also issues how FilteredConnection
handles multiple responses where it wasn't originally expected (e.g. additional response from network when shouldRefresh
is false).
useConnection
This hook replicates much of the core behavior that still makes sense to keep shared across components. That includes:
- Pagination (determining the correct cursor-based or batch-based arguments depending on the response)
- URL controls - both updating and reading to determine the correct query
- Retrieving more data, including handling that in state and providing the consumer with the correct response (including previous response data)
-
hasNextPage
logic. For the consumer to determine how they should structure their UI
Other aspects
UI Elements
A key aspect of FilteredConnection is how ts provides controlled UI elements. In some cases it can be helpful, in other cases it means needing work arounds like hideSearch
or 8 className
props. In the worst cases, it is actively stopping us from progressing with new designs because changing FilteredConnection
UI is so difficult. This hook assumes no UI, so it means consumers can completely decouple the connection logic from the elements that they want to render. Whilst we migrate, we will likely want to keep our UI consistent. To support this, there is a PR to break out FilteredConnection into generic UI components.
Tests
FilteredConnection previously had no/very little tests. I've added some extensive tests for useConnection
that test both cursor and batch pagination and URL behavior. This should make it much easier to refactor and change without worrying about breaking things.
Search and filters
This hook does not yet fully support the search
or filters
variables that are baked into FilteredConnection
. I want to put these into a separate PR once this is validated to be working well. There is some additional complexity here as previously FilteredConnection
fully controlled this and had some logic around each variable. Now we want consumers to control their own search <input />
and just provide useConnection
with the value, but still maintaining some control (e.g. URL behavior). I have a branch with a solution for this so will have a PR soon!
Examples
In order to correctly replicate this behaviour, and help write some effective tests, I have few branches with some example usage of this hook to replace FilteredConnection
. These might be helpful to review this PR, please take a look and feel free to have a play with them!
Example 1 - User Event Logs - Batch based pagination that updates and derives state from the URL
Example 2 - Access token settings - Batch based pagination that does not use the URL
Example 3 - Batch changes settings - Cursor based pagination. This example is bigger as I also updated a series of mutation
promises to use Apollo