Home >Web Front-end >JS Tutorial >How to Implement Debouncing in React Applications?
React owes its popularity to its component-based architecture. Often, we have components that listen to input changes and trigger API calls to retrieve data. We want to debounce these API calls to avoid making unnecessary requests.
import React, { useState, useEffect, Suspense } from 'react'; const debounce = (fn, delay) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => { fn(...args); }, delay); }; }; const SearchBox = () => { const [inputText, setInputText] = useState(''); const [searchResults, setSearchResults] = useState(null); const fetchResults = async (text) => { const response = await fetch(`/search?text=${text}`); const data = await response.json(); setSearchResults(data); }; const debouncedFetchResults = debounce(fetchResults, 500); useEffect(() => { if (!inputText) { return; } debouncedFetchResults(inputText); }, [inputText, debouncedFetchResults]); return ( <> <input type="search" value={inputText} onChange={(e) => setInputText(e.target.value)} /> <Suspense fallback={<div>Loading...</div>}> {searchResults && <Results results={searchResults} />} </Suspense> </> ); };
In this example, we use the debounce function to wrap the fetchResults function and only make the API call after 500ms of inactivity. We debounce the function on every change of the inputText state. We then use Suspense to render a placeholder while the results are being fetched.
Although React hooks are encouraged, you could also use class components to debounce:
import React, { Component } from 'react'; const debounce = (fn, delay) => { let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => { fn(...args); }, delay); }; }; class SearchBox extends Component { constructor(props) { super(props); this.state = { inputText: '', searchResults: null }; this.debouncedFetchResults = debounce(this.fetchResults, 500); } fetchResults = async (text) => { const response = await fetch(`/search?text=${text}`); const data = await response.json(); this.setState({ searchResults: data }); }; handleInputChange = (e) => { const text = e.target.value; this.setState({ inputText: text }); this.debouncedFetchResults(text); }; render() { return ( <> <input type="search" value={this.state.inputText} onChange={this.handleInputChange} /> {this.state.searchResults && <Results results={this.state.searchResults} />} </> ); } }
When attaching event handlers in React, remember that event objects are pooled to reduce GC pressure. If you want to access event properties asynchronously to the handler call, you can use the e.persist() method to prevent the event from being returned to the pool:
const onClick = (e) => { e.persist(); // Prevent the event object from being returned to the pool setTimeout(() => { // Access event properties here }, 0); }; <button onClick={onClick}>Click Me</button>
The above is the detailed content of How to Implement Debouncing in React Applications?. For more information, please follow other related articles on the PHP Chinese website!