#useQuery for search

12 messages · Page 1 of 1 (latest)

wintry sparrow
#

Hi everyone! Was wondering if anyone could help me figure out the best way to implement a search page such as this with React Query.

I would like a controlled search bar that the top which the user can type into. Although I do not want it to search until they have clicked the search button, I do want to be showing results initial so I would like it to fire a query when the page mounts with the default value.

Below is the code I have managed to come up with. I am using derived state so that I can control the input and but not update the query key (this firing a new query) until the user clicks the search button. Is there a better solution than this which removes this bad practice?

Thanks all!
`
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import axios from 'axios'

function App() {
const [searchTerm, setSearchTerm] = useState("1")

const [queryParams, setQueryParams] = useState(searchTerm)

const { data } = usePerson(queryParams)

const handleSearch = () => setQueryParams(searchTerm)

return (
<div>
<input onChange={(e) => setSearchTerm(e.target.value)} />
<button onClick={handleSearch}>Search</button>
<div>{data?.name}</div>
</div>
)
}

const usePerson = (queryParams: string) => {
return useQuery({
queryKey: ["person", queryParams],
queryFn: () => fetchPerson(queryParams)
})
}

const fetchPerson = async (queryParams: string) => {
const { data } = await axios.get(https://swapi.dev/api/people/${queryParams})
return data
}

export default App
`

shut aspen
#

Use a enabled useState which you pass to useQuery and toggle it on click

wintry sparrow
#

But if I do that it means everytime the user types into the search bar it will fire a new query right?

shut aspen
#

No. Enabled is false initially.

wintry sparrow
#

If its initially false it will mean that I don't fetch data on mount which is what I am hoping to do. Then once it becomes enabled, it will mean that every time the user types into the searchbar the query key will change and a new query will be fired. I only want to fire a query when they click search

#

I think this is what you are suggesting

`
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import axios from 'axios'

function App() {
const [searchTerm, setSearchTerm] = useState("1")

const [enabled, setEnabled] = useState(false)

const { data } = usePerson(searchTerm, enabled)

return (
<div>
<input onChange={(e) => setSearchTerm(e.target.value)} />
<button onClick={() => setEnabled(true)}>Search</button>
<div>{data?.name}</div>
</div>
)
}

const usePerson = (searchTerm: string, enabled: boolean) => {
return useQuery({
queryKey: ["person", searchTerm],
queryFn: () => fetchPerson(searchTerm),
enabled,
})
}

const fetchPerson = async (searchTerm: string) => {
const { data } = await axios.get(https://swapi.dev/api/people/${searchTerm})
return data
}

export default App
`

shut aspen
#

Looks good. If you want to query initially: enabled: enabled || searchTerm === „1“

wintry sparrow
#

Its not quite what I'm looking for

shut aspen
#

Why not?

topaz pendant
#

Couldn't you just only update searchTerm on submit?
That way you only need one state. And it can be populated with default data.

wintry sparrow
#

Yeah I've gone with this approach, was trying to use a controlled input component from a UI lib originally which is why I was wondering about the best way to make it work with a controlled input