What is the correct way to pass parameters to a React-query useQuery method that uses Axios
Asked Answered
H

2

31

I am currently building a Ruby on Rails Webpacker application with a React front end. I am at the point where I would like to create all the quires I need to make calls to my Rails API. I was loosely following this tutorial https://www.youtube.com/watch?v=0bKc_ch6MZY (https://github.com/daryanka/react-query-tutorial/blob/master/src/containers/Post.js, https://github.com/daryanka/react-query-tutorial/blob/master/src/Queries.js), in order to write some axios based query functions that I could use with react-query. I had no problem with getting the queries to behave as expected when the url for the endpoint was a hard coded string. When I attempted to pass in a parameter to make dynamic urls I ran into the issue of not having access to said parameter; specifically the "prodId" parameter. I did however notice that the "prodId" was inside the "key" parameter array like so:

queryKey: Array(2)
0: "product"
1: "1"
length: 2
enter code here

I could just access it from there but that approach does seem a little off, I also did not find any examples or documentation that attempted to access a parameter from the query key array. I would like to know what it is I am doing incorrectly with regards to passing in parameters? Were there some syntax changes in react-query that I am not taking into account?

react-query@^3.17.2

webpacker (5.2.1)

axios@^0.21.1

//Product.js

import axios from "axios"
import { getProduct } from "../../queries/products"
import { useQuery } from "react-query"

const prodId= '1'
const { data } = useQuery(['product', prodId], getProduct)

//queries/products.js
import axios from 'axios'

export const getProduct = async (key, { prodId }) => {
    console.log(opid)
    const { data } = await axios.get(`/api/v1/products/${prodId}`)
    return data
}
Harding answered 23/6, 2021 at 18:0 Comment(0)
E
81

The query function that you pass to react-query gets a queryContext injected, which is an object that consists of the queryKey (and some more information if you are using an infinite query). So yes, one correct way to access dependencies is through the queryKey:

export const getProduct = async ({ queryKey }) => {
    const [_, prodId] = queryKey
    const { data } = await axios.get(`/api/v1/products/${prodId}`)
    return data
}
const { data } = useQuery(['product', prodId], getProduct)

Another way is to use inline anonymous functions, which is well documented in the docs in: If your query function depends on a variable, include it in your query key

export const getProduct = async (prodId) => {
    const { data } = await axios.get(`/api/v1/products/${prodId}`)
    return data
}
const { data } = useQuery(['product', prodId], () => getProduct(prodId))
Exult answered 24/6, 2021 at 7:12 Comment(7)
I did actually give this approach a try after reading through the docs, I think in my flurry of iteration, I may not of had the correct query function parameter signature for the inline syntax. much thnaks. – Harding
how to pass query context along with pageParam parameter which is used to fetch next page in useInfiniteQuery? – Foolscap
it works exactly the same way. pageParam is just another field in the context that you can destruct like the queryKey,and it will be filled by react-query depending on what you return from getNextPagePraam – Exult
First off @Exult thanks for your responses! I've read a couple of your answers through SO and GH so much appreciated πŸ™. What am I missing? This seems like a basic requirement for using async fns and this is overly complicated way to do it. – Agave
@SunnyPatel I don't know what you are missing - I don't even know what your question is ... – Exult
How is the second method used with the params object? Eg. useQuery( ... , {onError:(error)=>{...}}) – Seger
please how to use multiple parameters ? – Joey
D
8

I'm using the following (typescript) to send parameters to my custom useQuery hook.

import { useQuery } from 'react-query'
import service from '../api'

const queryKey = 'my-query-key'
type useProductsParams = Parameters<typeof service.listProducts>

const useProducts = (...params: useProductsParams) => {
  return useQuery(queryKey, () => service.getProduct(...params))
}

export default useProducts
Deejay answered 24/8, 2022 at 14:16 Comment(1)
Based on the documentation for QueryKeys, keys have to be an array. From Docs: Query keys have to be an Array at the top level, and can be as simple as an Array with a single string, or as complex as an array of many strings and nested objects. – Teratogenic

© 2022 - 2024 β€” McMap. All rights reserved.