Skip to content

GraphQL Client: Add `useConnection` hook to replace `<FilteredConnection />`

Administrator requested to merge tr/add-use-connection-hook into main

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

Merge request reports

Loading