如何在重新渲染时更新 API 调用?

How can I update the API call on a re-render?

我正在自学 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

问题可能出在这里:

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

中找到更多信息

有些东西你应该看看。要防止在搜索框上输入多个 api 调用,请使用一种称为 debounce 的技术,您可以使用反应挂钩实现此目的:

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])
}