用React Hooks防弹跳

今天,我将向您展示如何创建useDebounce钩子,该钩子可让您超级简单地推迟API调用,以使它们不会经常发生。


我还创建了一个使用我们的钩子的演示。它搜索Marvel Comics API,并且useDebounce挂钩使您可以避免每次击键时服务器调用。


图片


很优雅吧?好的,现在让我们开始编写代码!


, , . , , , . 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;
}

在这里他在你的面前!现在我们有了一个用于延迟值的钩子,通过它我们可以直接在组件主体中延迟任何值的更改。然后可以将延迟的值添加到useEffect依赖项数组中,而不是将自身的可变值添加到其中,以将调用频率限制为所需的效果。


这是CodeSandbox上Marvel Comic Search演示演示


如果您喜欢它,可以查看我的关于React挂钩React应用程序构建器的博客并对其进行评分


All Articles