Supongamos que tengo un componente de Search que, cuando el usuario escribe algo, activa una solicitud de API para buscar lo que se escribe. Cuando se usa useEffect Hook de React, sería fácil acelerar las solicitudes de API con una combinación de setTimeout y clearTimeout (que se coloca en la función de limpieza que devuelve useEffect ). Sin embargo, ¿cómo se puede hacer esto en la versión del componente Clase de Search dentro del método de ciclo de vida componentDidUpdate ?
function Search() { const [term, setTerm] = React.useState(""); const [results, setResults] = React.useState([]); React.useEffect(() => { if(term) const timeOutId = window.setTimeout(() => { if (term) (async () => { const { data } = await axios.get( "https://en.wikipedia.org/w/api.php", { params: { action: "query", list: "search", origin: "*", format: "json", srsearch: term, }, } ); setResults(data.query.search); })(); }, 500); } return () => window.clearTimeout(timeoutId); }, [term]); return ( /* some JSX */ ); } class Search extends React.Component { state = { term: '', results: [] } componentDidUpdate(prevProps, prevState) { /* ??? */ } render() { return ( /* some JSX */ ); } }Si bien podría usar componentDidUpdate() para esto, sería más fácil manejar la mayor parte de la lógica en el controlador onChange de su entrada.
Hay dos matices importantes a tener en cuenta aquí. La primera es que timeoutId no debe estar en estado para que no active renderizaciones adicionales. La segunda parte es limpiar el tiempo de espera después de que el componente se desmonte a través de componentWillUnmount() , de modo que no deje ninguna llamada pendiente después de que su componente ya no exista.
class Foo extends React.PureComponent { timeoutId = undefined; state = { term: "" }; // Note that this method is bound so we can pass it directly to `onChange` onTermChange = (event) => { if (this.timeoutId) { clearTimeout(this.timeoutId); } const term = event.target.value; this.setState({ term }); this.timeoutId = setTimeout(() => { this.timeoutId = undefined; console.log(`timer fired with "${term}"`); }, 1000); }; componentWillUnmount() { if (this.timeoutId) { clearTimeout(this.timeoutId); } } render() { return ( <input value={this.state.term} onChange={this.onTermChange} /> ); } } ReactDOM.render(<Foo />, document.querySelector("#app")); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="app"></div>