英文:
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'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 = () => {
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!
答案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(
() => {
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 />)
<!-- language: lang-html -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>
<!-- 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(
() => {
axios
.get("", {search: debouncedSearch, page})
.then(setResults)
.catch(console.error)
},
[page, debouncedSearch])
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论