What's the best practice for debounce on search changes and instant fetch on page changes with useState and useEffect in React?

huangapple go评论76阅读模式
英文:

What's the best practice for debounce on search changes and instant fetch on page changes with useState and useEffect in React?

问题

I'm having two state variables, page and search, and want to refetch data every time one of these are changed,

For search change I want to do debounce, and for page changes need to fetch instantly.

const [page, setPage] = useState()
const [search, setSearch] = useState();

const fetch = () => {
   axios.get("", {search, page}) // nvm the syntax
}

useEffect(()=>{
   const timer = setTimeout(()=>{ fetch() }, 3000)

   return () => { clearTimeout(timer) }
}, [search])

useEffect(()=>{
   fetch();
}, [page])

Unfortunately I'm getting eslint exhaustive deps warning here, if I fix these warnings, then fetch is called twice on change, could you please explain what's the correct way/best practice to tackle this? Thanks!

<details>
<summary>英文:</summary>

I&#39;m having two state variables, `page` and `search`, and want to refetch data every time one of these are changed, 

For search change I want to do debounce, and for page changes need to fetch instantly.

```ts
const [page, setPage] = useState()
const [search, setSearch] = useState();

const fetch = () =&gt; {
   axios.get(&quot;&quot;, {search, page}) // nvm the syntax
}

useEffect(()=&gt;{
   const timer = setTimeout(()=&gt;{ fetch() }, 3000)

   return () =&gt; { clearTimeout(timer) }
}, [search])

useEffect(()=&gt;{
   fetch();
}, [page])

Unfortunately I'm getting eslint exhaustive deps warning here, if I fix these warnings, then fetch is called twice on change, could you please explain what's the correct way/best practice to tackle this? Thanks!

答案1

得分: 2

你可以编写一个useDebouncedValue函数 -

const { useEffect, useState } = React

function useDebouncedValue(value, delay) {
  const [state, setState] = useState(value)
  useEffect(
    () => {
      const t = setTimeout(setState, delay, value)
      return () => { clearTimeout(t) }
    },
    [value, delay]
  )
  return state
}

function App() {
  const [foo, setFoo] = useState("hello")
  const debouncedFoo = useDebouncedValue(foo, 1000)
  return <div>
    <input onChange={e => setFoo(e.target.value)} value={foo} />
    debounced: {debouncedFoo}
  </div>
}

ReactDOM.createRoot(document.querySelector("#app")).render(<App />)

在你的组件中使用它可能会像这样 -

const [page, setPage] = useState()
const [search, setSearch] = useState()
const debouncedSearch = useDebouncedValue(search, 3000)

useEffect(
  () => {
    axios
      .get("", {search: debouncedSearch, page})
      .then(setResults)
      .catch(console.error)
  },
  [page, debouncedSearch]
)
英文:

You could write a useDebouncedValue -

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

const { useEffect, useState } = React

function useDebouncedValue(value, delay) {
  const [state, setState] = useState(value)
  useEffect(
    () =&gt; {
      const t = setTimeout(setState, delay, value)
      return () =&gt; { clearTimeout(t) }
    },
    [value, delay]
  )
  return state
}

function App() {
  const [foo, setFoo] = useState(&quot;hello&quot;)
  const debouncedFoo = useDebouncedValue(foo, 1000)
  return &lt;div&gt;
    &lt;input onChange={e =&gt; setFoo(e.target.value)} value={foo} /&gt;
    debounced: {debouncedFoo}
  &lt;/div&gt;
}

ReactDOM.createRoot(document.querySelector(&quot;#app&quot;)).render(&lt;App /&gt;)

<!-- language: lang-html -->

&lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.development.js&quot;&gt;&lt;/script&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.development.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

Using it in your component might look something like this -

const [page, setPage] = useState()
const [search, setSearch] = useState()
const debouncedSearch = useDebouncedValue(search, 3000)

useEffect(
  () =&gt; {
    axios
      .get(&quot;&quot;, {search: debouncedSearch, page})
      .then(setResults)
      .catch(console.error)
  },
  [page, debouncedSearch])
)

huangapple
  • 本文由 发表于 2023年5月24日 21:03:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76323860.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定