Anti-rebond avec React Hooks

Aujourd'hui, je vais vous montrer comment créer un hook useDebounce qui vous permet de reporter très simplement les appels d'API afin qu'ils ne se produisent pas trop souvent.


J'ai également créé une démo qui utilise notre crochet. Il recherche les API Marvel Comics et le crochet useDebounce vous permet d'éviter les appels du serveur à chaque frappe.


image


Assez élégant, hein? Ok, passons maintenant au code!


, , . , , , . useEffect, , . useState useEffect, .


import React, { useState, useEffect } from 'react';
import useDebounce from './use-debounce';

// 
function App() {
  //       
  const [searchTerm, setSearchTerm] = useState('');
  //       
  const [results, setResults] = useState([]);
  //     (    API)
  const [isSearching, setIsSearching] = useState(false);

  //     ,    searchTerm.
  //      (  ) ...
  // ...    500ms   .
  //      searchTerm.
  //   ,      ,    
  //           .
  const debouncedSearchTerm = useDebounce(searchTerm, 500);

  //    
  //   useEffect,     
  useEffect(
    () => {
      //       (  -)
      if (debouncedSearchTerm) {
        //   isSearching
        setIsSearching(true);
        //    
        searchCharacters(debouncedSearchTerm).then(results => {
          //    false, -  
          setIsSearching(false);
          //    
          setResults(results);
        });
      } else {
        setResults([]);
      }
    },
    //    useEffect
    //  useEffect       ...
    // ...    ,      ...
    //   searchTerm     500ms.
    [debouncedSearchTerm]
  );

  //   UI     
  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>
  );
}

//    
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';

//  
export default function useDebounce(value, delay) {
  //      
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(
    () => {
      //  debouncedValue  value ( ) 
      //   
      const handler = setTimeout(() => {
        setDebouncedValue(value);
      }, delay);

      //   ,     ,  ...
      // ... useEffect  . useEffect   ,   ...
      // ... value   (   ).
      //     debouncedValue,   value ...
      // ...     .
      //     .
      //     :    -  ...
      // ...     ,   ,  debouncedValue...
      // ...     ,      ,  500ms.
      return () => {
        clearTimeout(handler);
      };
    },
    //  ,    
    //       "delay"    ...
    // ...      .
    [value]
  );

  return debouncedValue;
}

Et le voici devant vous! Nous avons maintenant un crochet pour les valeurs différées avec lequel nous pouvons retarder le changement de toute valeur directement dans le corps de notre composant. La valeur différée peut ensuite être ajoutée au tableau de dépendances useEffect, au lieu des valeurs mutables elles-mêmes, pour limiter la fréquence des appels à l'effet souhaité.


Voici la démo de démonstration de Marvel Comic Search sur CodeSandbox.


Si vous l'avez aimé, vous pouvez jeter un œil et évaluer mon blog sur les crochets React et le générateur d'applications React.


All Articles