【问题标题】:How can I update the API call on a re-render?如何在重新渲染时更新 API 调用?
【发布时间】:2019-04-22 01:48:12
【问题描述】:

我正在自学 React Hooks,我想在用户在搜索框中输入内容时更新 API 调用。一种实时搜索。我收集到该事件仅在页面加载时触发,但我该如何解决这个问题?

示例:https://codesandbox.io/s/6x1xp57zmk

import React, {useState, useEffect} from 'react';

function App() {

  const [cardNames, setCardName] = useState([])

  const rezCards = async () => {
    //const rez = await fetch('https://api.scryfall.com/cards?page=3')
    const rez = await fetch ('https://api.scryfall.com/catalog/card-names')
    const json = await rez.json()
    setCardName(json.data)
  }

  useEffect(() => {
    rezCards()
  },[])

  return <ul>{cardNames
    .slice(0,50)
    .map(
      (cardName) => {
        return <li key={cardName}>{cardName}</li>
      }
    )}</ul>
}

export default App

【问题讨论】:

    标签: reactjs state react-hooks


    【解决方案1】:

    有些东西你应该看看。为了防止在搜索框上键入多个 api 调用,请使用一种称为 debounce 的技术,您可以通过 react hooks 实现这一点:

    function useDebounce(value, delay) {
      const [debouncedValue, setDebouncedValue] = useState(value);
    
      useEffect(
        () => {
          const handler = setTimeout(() => {
            setDebouncedValue(value);
          }, delay);
    
          return () => {
            clearTimeout(handler);
          };
        },
        [value, delay],
      );
    
      return debouncedValue;
    }
    
    function App() {
    
      const debouncedInput = useDebounce(searchInputValue, 300);
      useEffect(() => {
        rezCards()
      },[debouncedInput])
    }
    

    【讨论】:

      【解决方案2】:

      问题可能出在这里:

      useEffect(() => {
          rezCards()
      },[])
      

      您将第二个参数保留为空数组,这导致 useEffect 在组件挂载时仅运行一次,与 componentDidMount 相同。

      如果你想在状态改变时触发useEffect,你可以添加状态作为钩子的依赖,例如

      const { callThisEffectWhenThisValueIsChanged, changeValue } = useState('');
      
      useEffect(() => {
          // Do anything with here, for eg call APIs
      },[callThisEffectWhenThisValueIsChanged])
      
      changeValue(newValue);
      

      因此,在您的 CodeSandbox 代码中,您只需在依赖项中添加您的 searchInput,它就会在搜索输入发生更改时再次调用该钩子。

      useEffect(() => {
          rezCards();
      }, [searchInput]);
      

      永远记住,每当你的效果使用任何状态时,你都需要将状态添加为效果挂钩的依赖项

      您可以在React Hook doc找到更多信息

      【讨论】:

      • 嘿,这行得通!但它是添加到结果而不是替换它,所以它从一堆皮卡丘卡片开始,如果我输入“charmander”,它会添加所有名称中带有“cha”的卡片(冠军等),依此类推键入更多字母。如何重置那里的状态?
      • 嗨@BrianPaskoff 如果您检查CodeSandbox 上的控制台,您会看到很多复制key 以进行渲染的错误,这就是为什么一些&lt;li&gt; 标记将重用之前的内容值,即皮卡丘数据。尝试将 &lt;li key={cardName.name}&gt; 更改为 &lt;li key={cardName.id}&gt; 而应该是唯一的
      • 您可以在reactjs.org/docs/reconciliation.html#keys 上查看有关 React 中 key 如何工作的更多详细信息
      • 哇,我不知道键有那么重要,我认为它们是强烈建议用于使代码更具可读性的标识符,但不是进入的东西使整个事情打勾。现在可以按预期工作了,谢谢!
      • 确实,如果我们没有意识到这一点,它会导致任何不希望的输出:) 如果您觉得答案有用,请记得点赞!祝你有美好的一天!
      猜你喜欢
      • 2016-12-30
      • 2020-04-23
      • 2022-01-24
      • 2022-01-25
      • 2022-06-27
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      相关资源
      最近更新 更多