Skip to content

feat: Additional Router Level Tanstack Query Methods #3012

@JonParton

Description

@JonParton

Describe the feature you'd like to request

ℹ️ Transferring here so the conversation isn't left on a completed PR

As requested by @TkDodo here currently we only expose the invalidate method on Routers from the tRPC Proxy (Implemented in #2711); However Tanstack-Query exposes many other fuzzy key match methods which are below:



@TkDodo Would like to see if we can implement the other functionality as currently there is no way of doing these on our existing API.

ℹ️ Note: We have already discounted adding the Root level functionality here with input from @juliusmarminge on the current approach.

Describe the solution you'd like to see

When interacting with the tRPC utils proxy (useContext) on the client side these methods should be exposed at any router level for use:

For Exmaple:

import { trpc } from '../utils/trpc';

function MyComponent() {

  const utils = trpc.useContext()

  utils.post.setQueryDefaults({ staleTime: Infinity }) // Where post is a router containing multiple, queries, mutations or sub routers

  utils.post.setMutationDefaults({ /* ...Mutation Default here such as a default onSuccess function */})

  // Defaults set will then apply to future instantiated hooks. 

  const { data: posts } = trpc.post.getAll.useQuery()
  const { data: postSeries } = trpc.post.getPostSeries.useQuery()
  const appPost = trpc.post.add.useMutation()

  utils.post.cancelQueries() // Cancelles both post queries above
    
})

  // [...]
}

Obviously there is more research in to how each of these methods would interact and a few differences in the API we would want to expose (Such as ommiting a few keys to limit the ability to set the mutationFn for MutationDefaults etc) but from a brief look they all seem to have value although some are nuanced use cases.

Describe alternate solutions

  1. It looks like we have started to consider some overrides defined on the createTRPCReact function ... Some of these may fit in here too such as the mutation defaults? Although I guess we would want to be specific to a particular router rather then across the query client! ... being able to define them multiple times in code rather then on initialisation may also allow some greater flexibility but not 100% sure on the consequences of doing so in Tanstack Query etc ...

  1. Make people just construct these functions by using the internally generated QueryKey and using the vanilla Tanstack Query useQueryClient() api. However, we miss the opportunity here to handle the QueryKey generation for developers and also to provide type safety around the ones that return values / accept inputs

To help with this we could add a .getQueryKey(input) to our utils object... A kind of typesafe query key builder that could be called at a router or procedure level and used with the vanilla Tanstack-Query queryClient methods

const queryClient = useQueryClient()
queryClient.removeQueries(utils.post.getById.getQueryKey()) // QueryKey => [["post","getById"]]
queryClient.removeQueries(utils.post.getById.getQueryKey({userId:10})) // QueryKey => [["post","getById"],{userId:10}]
queryClient.setQueryDefaults(utils.post.getQueryKey(), { staleTime: Infinity }) // [["post"]]

Plausibly with this exposed you could also then infer the correct types of any returns in userland using the provided tRPC infer methods ... but that could get tricky for some!


  1. Only implement a sub set of the above requested methods!

  1. A mixture of the above 🤷

Additional information

Before anyone puts any effort into this I think it would be worth a bit of input from the A Team (@KATT , @sachinraja , @juliusmarminge etc) on if we think this addition to the API surface is a good idea and a finger in air on if we are happy to add the extra types that may effect TS Performance (🤷 ... couldn't see an effect from adding invalidate() after the optimisations that have been done recently!)

👨‍👧‍👦 Contributing

  • 🙋‍♂️ Yes, I'd be down to file a PR implementing this feature! (Although it may be a slow burn if I implement!)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions