【问题标题】:Debounce Input while performing a query in `urql` GraphQL Client in React.js在 React.js 中的“urql”GraphQL 客户端中执行查询时去抖动输入
【发布时间】:2021-04-16 13:53:17
【问题描述】:

我有一个像 https://zillow.github.io/react-slider 这样的双滑块,带有 minmax 值。当其中一个滑块发生变化时,它会调用一个查询。

但由于查询量很大,因此需要花费大量时间,我需要找到一种方法来使用 debounce,这样查询就不会经常被调用。

我确实找到了一个很好的解决方案 → https://stackoverflow.com/a/58594348/6141587 仅使用 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 时是有意义的。我该如何解决这个问题?

【问题讨论】:

  • 立即传递道具,但在获取组件内部使用超时(延迟保存道具到状态),使用状态中的值进行查询...结合useEffect/loading/onComplete states/events超时
  • @xadm 看起来很简单,谢谢 :)

标签: javascript reactjs graphql debounce urql


【解决方案1】:

我找到了解决方案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 中传递的状态排队去抖动。我将相同的去抖状态传递给&lt;AcquisitionList minPrice={acquisitionPriceRange[0]} maxPrice={acquisitionPriceRange[1]} /&gt;

【讨论】:

猜你喜欢
  • 2021-01-26
  • 2020-04-28
  • 2020-03-14
  • 1970-01-01
  • 2019-06-21
  • 2013-03-10
相关资源
最近更新 更多