React.js 在 `urql` GraphQL Client 中执行查询时去抖动输入
Debounce Input while performing a query in `urql` GraphQL Client in React.js
我有一个像 https://zillow.github.io/react-slider 这样的双滑块,具有 min
和 max
值。它会在其中一个滑块发生变化时调用查询。
但是由于查询很大,需要花费很多时间,而且我需要找到一种使用去抖动的方法,这样查询就不会经常被调用。
我确实找到了一个很好的解决方案 → 仅使用 React.js 但不确定如何将其与 urql
一起使用?
Home.tsx
import React from 'react'
import ReactSlider from 'react-slider'
import debounce from 'lodash.debounce'
import { AcquisitionList } from '../components/index'
const Home = () => {
const [price, setPrice] = React.useState([0, 1000000000])
const debounceSetPrice = React.useCallback(debounce(setPrice, 2000), [])
return (
<div className="h-full p-8 text-white bg-blue-gray-900">
<div className="flex items-center justify-center">
<div className="flex flex-col items-center text-white">
<span className="">Min</span>
<input
className="text-lg font-bold text-center min-w-16 rounded-xl bg-gradient-to-b from-indigo-700 bg-blue-gray-900"
name="minPrice"
type="text"
value={price[0]}
onChange={(e) => {
const minPrice = e.target.value
const maxPrice = price[1]
debounceSetPrice([minPrice, maxPrice])
}}
/>
</div>
<ReactSlider
step={1}
min={0}
max={1000000000}
className="w-1/2 h-5 pr-2 mx-8 my-4 rounded-md bg-blue-gray-700 cursor-grab"
thumbClassName="absolute w-8 h-8 cursor-[grab] rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 ring-offset-blue-gray-700 -top-1 bg-gradient-to-b from-indigo-700 bg-blue-gray-900 focus:ring-indigo-500 focus:border-indigo-500"
ariaLabel={['Min Price', 'Max Price']}
value={price}
onChange={(price) => {
debounceSetPrice(price)
}}
/>
<div className="flex flex-col items-center text-white">
<span className="">Max</span>
<input
className="text-lg font-bold text-center min-w-16 rounded-xl bg-gradient-to-b from-indigo-700 bg-blue-gray-900"
name="maxPrice"
type="text"
value={price[1]}
onChange={(e) => {
const minPrice = price[0]
const maxPrice = e.target.value
debounceSetPrice([minPrice, maxPrice])
}}
/>
</div>
</div>
<AcquisitionList minPrice={price[0]} maxPrice={price[1]} />
</div>
)
}
export default Home
AcquisitionsList.tsx
import React from 'react'
import { useQuery } from 'urql'
import { Card } from '../components/index'
import {
GET_ALL_ACQUISITIONS,
GET_ACQUISITIONS_BY_PRICE,
} from '../graphql/index'
export const AcquisitionList = ({ minPrice, maxPrice }) => {
const [result, reexecuteQuery] = useQuery({
query: GET_ALL_ACQUISITIONS,
variables: {
minPrice,
maxPrice,
skip: 10,
take: 10,
},
})
const { data, fetching, error } = result
if (fetching) return <p>Loading...</p>
if (error) return <p>Oh no... {error.message}</p>
return (
<div className="flex flex-wrap justify-center mt-10">
{data.getAllAcquisitions.map((startup, i) => {
return <Card key={i} startup={startup} index={i} />
})}
</div>
)
}
我当前的解决方案延迟滑块值更改 2 秒,这在我直接调用 debounceSetPrice
时很有意义。我该如何解决这个问题?
我找到了解决方案 thanks to URQL maintainer Jovi:
const Home = () => {
const priceRange = [0, 100000000000] // minPrice = 0, maxPrice = 100 billion
const timeout = React.useRef(null)
const [acquisitionPriceRange, setAcquisitionPriceRange] = React.useState(
priceRange
)
const [price, setPrice] = React.useState(priceRange)
React.useEffect(() => {
timeout.current = setTimeout(() => {
setAcquisitionPriceRange(price)
timeout.current = null
}, 2000)
return () => {
if (timeout.current) clearTimeout(timeout.current)
}
}, [price])
return (
<div className="h-full min-h-screen p-8 text-white bg-blue-gray-900">
.
.
.
<AcquisitionList
minPrice={acquisitionPriceRange[0]}
maxPrice={acquisitionPriceRange[1]}
undisclosed={enabled}
sortByPrice={sortByPrice}
sortByStartupName={sortByStartupName}
/>
</div>
)
}
export default Home
我同步设置值,因此 UI 不会延迟并为我在 React.useEffect
中传递的状态排队去抖动。我将相同的去抖状态传递给 <AcquisitionList minPrice={acquisitionPriceRange[0]} maxPrice={acquisitionPriceRange[1]} />
我有一个像 https://zillow.github.io/react-slider 这样的双滑块,具有 min
和 max
值。它会在其中一个滑块发生变化时调用查询。
但是由于查询很大,需要花费很多时间,而且我需要找到一种使用去抖动的方法,这样查询就不会经常被调用。
我确实找到了一个很好的解决方案 → 仅使用 React.js 但不确定如何将其与 urql
一起使用?
Home.tsx
import React from 'react'
import ReactSlider from 'react-slider'
import debounce from 'lodash.debounce'
import { AcquisitionList } from '../components/index'
const Home = () => {
const [price, setPrice] = React.useState([0, 1000000000])
const debounceSetPrice = React.useCallback(debounce(setPrice, 2000), [])
return (
<div className="h-full p-8 text-white bg-blue-gray-900">
<div className="flex items-center justify-center">
<div className="flex flex-col items-center text-white">
<span className="">Min</span>
<input
className="text-lg font-bold text-center min-w-16 rounded-xl bg-gradient-to-b from-indigo-700 bg-blue-gray-900"
name="minPrice"
type="text"
value={price[0]}
onChange={(e) => {
const minPrice = e.target.value
const maxPrice = price[1]
debounceSetPrice([minPrice, maxPrice])
}}
/>
</div>
<ReactSlider
step={1}
min={0}
max={1000000000}
className="w-1/2 h-5 pr-2 mx-8 my-4 rounded-md bg-blue-gray-700 cursor-grab"
thumbClassName="absolute w-8 h-8 cursor-[grab] rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 ring-offset-blue-gray-700 -top-1 bg-gradient-to-b from-indigo-700 bg-blue-gray-900 focus:ring-indigo-500 focus:border-indigo-500"
ariaLabel={['Min Price', 'Max Price']}
value={price}
onChange={(price) => {
debounceSetPrice(price)
}}
/>
<div className="flex flex-col items-center text-white">
<span className="">Max</span>
<input
className="text-lg font-bold text-center min-w-16 rounded-xl bg-gradient-to-b from-indigo-700 bg-blue-gray-900"
name="maxPrice"
type="text"
value={price[1]}
onChange={(e) => {
const minPrice = price[0]
const maxPrice = e.target.value
debounceSetPrice([minPrice, maxPrice])
}}
/>
</div>
</div>
<AcquisitionList minPrice={price[0]} maxPrice={price[1]} />
</div>
)
}
export default Home
AcquisitionsList.tsx
import React from 'react'
import { useQuery } from 'urql'
import { Card } from '../components/index'
import {
GET_ALL_ACQUISITIONS,
GET_ACQUISITIONS_BY_PRICE,
} from '../graphql/index'
export const AcquisitionList = ({ minPrice, maxPrice }) => {
const [result, reexecuteQuery] = useQuery({
query: GET_ALL_ACQUISITIONS,
variables: {
minPrice,
maxPrice,
skip: 10,
take: 10,
},
})
const { data, fetching, error } = result
if (fetching) return <p>Loading...</p>
if (error) return <p>Oh no... {error.message}</p>
return (
<div className="flex flex-wrap justify-center mt-10">
{data.getAllAcquisitions.map((startup, i) => {
return <Card key={i} startup={startup} index={i} />
})}
</div>
)
}
我当前的解决方案延迟滑块值更改 2 秒,这在我直接调用 debounceSetPrice
时很有意义。我该如何解决这个问题?
我找到了解决方案 thanks to URQL maintainer Jovi:
const Home = () => {
const priceRange = [0, 100000000000] // minPrice = 0, maxPrice = 100 billion
const timeout = React.useRef(null)
const [acquisitionPriceRange, setAcquisitionPriceRange] = React.useState(
priceRange
)
const [price, setPrice] = React.useState(priceRange)
React.useEffect(() => {
timeout.current = setTimeout(() => {
setAcquisitionPriceRange(price)
timeout.current = null
}, 2000)
return () => {
if (timeout.current) clearTimeout(timeout.current)
}
}, [price])
return (
<div className="h-full min-h-screen p-8 text-white bg-blue-gray-900">
.
.
.
<AcquisitionList
minPrice={acquisitionPriceRange[0]}
maxPrice={acquisitionPriceRange[1]}
undisclosed={enabled}
sortByPrice={sortByPrice}
sortByStartupName={sortByStartupName}
/>
</div>
)
}
export default Home
我同步设置值,因此 UI 不会延迟并为我在 React.useEffect
中传递的状态排队去抖动。我将相同的去抖状态传递给 <AcquisitionList minPrice={acquisitionPriceRange[0]} maxPrice={acquisitionPriceRange[1]} />