React Debounce使用 React Hooks 进行去抖动
今天我将向你展示如何构建一个 useDebounce React Hook,它能够非常轻松地对 API 调用进行去抖动,从而确保它们不会执行得太频繁。我还制作了一个使用这个 Hook 的演示。它搜索 Marvel Comic API,并使用 useDebounce 来防止每次按键时都触发 API 调用。
是不是很漂亮?好了,现在开始代码吧!
首先,让我们弄清楚如何使用这个钩子,并以此为指导来实际实现钩子逻辑。我们设计这个钩子的目的不是对 API 请求的调用进行去抖动处理,而是对组件渲染函数中的任何值进行去抖动处理。然后,我们将结合使用 和 ,useEffect
以便在输入值发生变化时触发新的 API 请求。本代码示例假设读者对useState
和钩子有所了解,你可以在React Hook 文档useEffect
中了解它们。
import React, { useState, useEffect } from 'react';
import useDebounce from './use-debounce';
// Usage
function App() {
// State and setter for search term
const [searchTerm, setSearchTerm] = useState('');
// State and setter for search results
const [results, setResults] = useState([]);
// State for search status (whether there is a pending API request)
const [isSearching, setIsSearching] = useState(false);
// Now we call our hook, passing in the current searchTerm value.
// The hook will only return the latest value (what we passed in) ...
// ... if it's been more than 500ms since it was last called.
// Otherwise, it will return the previous value of searchTerm.
// The goal is to only have the API call fire when user stops typing ...
// ... so that we aren't hitting our API rapidly.
const debouncedSearchTerm = useDebounce(searchTerm, 500);
// Here's where the API call happens
// We use useEffect since this is an asynchronous action
useEffect(
() => {
// Make sure we have a value (user has entered something in input)
if (debouncedSearchTerm) {
// Set isSearching state
setIsSearching(true);
// Fire off our API call
searchCharacters(debouncedSearchTerm).then(results => {
// Set back to false since request finished
setIsSearching(false);
// Set results state
setResults(results);
});
} else {
setResults([]);
}
},
// This is the useEffect input array
// Our useEffect function will only execute if this value changes ...
// ... and thanks to our hook it will only change if the original ...
// value (searchTerm) hasn't changed for more than 500ms.
[debouncedSearchTerm]
);
// Pretty standard UI with search input and results
return (
<div>
<input
placeholder="Search Marvel Comics"
onChange={e => setSearchTerm(e.target.value)}
/>
{isSearching && <div>Searching ...</div>}
{results.map(result => (
<div key={result.id}>
<h4>{result.title}</h4>
<img
src={`${result.thumbnail.path}/portrait_incredible.${
result.thumbnail.extension
}`}
/>
</div>
))}
</div>
);
}
// API search function
function searchCharacters(search) {
const apiKey = 'f9dfb1e8d466d36c27850bedd2047687';
const queryString `apikey=${apiKey}&titleStartsWith=${search}`;
return fetch(
`https://gateway.marvel.com/v1/public/comics?${queryString}`,
{
method: 'GET'
}
)
.then(r => r.json())
.then(r => r.data.results)
.catch(error => {
console.error(error);
return [];
});
}
好的,看起来不错!现在让我们构建实际的钩子,以便我们的应用程序正常运行。
import React, { useState, useEffect } from 'react';
// Our hook
export default function useDebounce(value, delay) {
// State and setters for debounced value
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(
() => {
// Set debouncedValue to value (passed in) after the specified delay
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
// Return a cleanup function that will be called every time ...
// ... useEffect is re-called. useEffect will only be re-called ...
// ... if value changes (see the inputs array below).
// This is how we prevent debouncedValue from changing if value is ...
// ... changed within the delay period. Timeout gets cleared and restarted.
// To put it in context, if the user is typing within our app's ...
// ... search box, we don't want the debouncedValue to update until ...
// ... they've stopped typing for more than 500ms.
return () => {
clearTimeout(handler);
};
},
// Only re-call effect if value changes
// You could also add the "delay" var to inputs array if you ...
// ... need to be able to change that dynamically.
[value]
);
return debouncedValue;
}
就这样!我们现在有了一个去抖钩子,可以用来在组件主体中对任何值进行去抖动处理。然后,可以将去抖动值(useEffect
而不是非去抖动值)添加到 的输入数组中,以限制该效果的调用频率。
还可以看看我的React 代码库生成器。它将提供美观的 UI、身份验证、数据库、支付等功能。成千上万的 React 开发者使用它来快速构建和发布应用。
文章来源:https://dev.to/gabe_ragland/debouncing-with-react-hooks-jci