【问题标题】:Infinite loop in useEffect when setting state设置状态时useEffect中的无限循环
【发布时间】:2019-10-20 22:13:21
【问题描述】:

我有一个关于 useEffectuseState 里面的问题。 我正在构建一个组件:

const [id, setId] = useState(0);
const [currencies, setCurrencies] = useState([]);

...
useEffect(()=> {
const getCurrentCurrency = async () => {
            const response = await fetch(`https://api.exchangeratesapi.io/latest?base=GBP`);
            const data = await response.json();
            const currencyArray = [];
            const {EUR:euro ,CHF:franc, USD: dolar} = data.rates;
            currencyArray.push(euro, dolar/franc,1/dolar);
            console.log("currencyArray", currencyArray);
             setCurrencies(currencies => [...currencies, currencyArray]);
          }
          getCurrentCurrency();
    }, [id, currencies.length]);

仅在 id 更改时用于发出新的 API 请求。每次更改 ID 时,我都需要使用新数据发出新请求。就我而言,现在我有无限循环。我尝试使用依赖项,但它没有按预期工作。

【问题讨论】:

  • 如果你只想在ID改变时更新,为什么需要currencies.length1
  • 即使只有 id 依赖也存在无限循环。我更改了 useEffect 中的状态,所以这是原因,但我不知道如何解决它。我尝试使用多个依赖项(这就是我添加 currencies.length 的原因)但它不起作用
  • 我的 sn-p 的第一行。
  • id 来自哪里?
  • const [id, setId] = useState(0); 然后我在处理程序中的某处更改它,以便在滑块中的幻灯片之间移动,如下所示:const goToPrevSlide = () => { id === 0 ? setId(2) : setId(id-1); } const goToNextSlide = () =>{ id === 2 ? setId(0) : setId(id+1); }

标签: reactjs react-hooks


【解决方案1】:

您在每次调用时都更改了一个值 (currencies.length),useEffect 依赖于 ([id, currencies.length])。

因此会导致无限循环。

useEffect(() => {
  const getCurrentCurrency = async () => {
    // ...
    currencyArray.push(euro, dolar / franc, 1 / dolar);

//                    v The length is changed on every call
    setCurrencies(currencies => [...currencies, currencyArray]);
  };
  getCurrentCurrency();
//                    v Will called on every length change
}, [id,currencies.length]);

当您使用函数式 useStatecurrencies => [...currencies, currencyArray] 时,您不需要 currencies.length 作为依赖项

useEffect(() => {
  const getCurrentCurrency = async () => {
    ...
  }
  getCurrentCurrency();

}, [id]);

此外,由于它似乎是一个交换应用程序,您可能会使用一个间隔来获取货币:

useEffect(() => {
  const interval = setInterval(getCurrency, 5000);
  return () => clearInterval(interval);
}, []);

【讨论】:

  • 好的,但是如果我只有一个依赖项(id),为什么这不起作用。我的逻辑在这里描述: 1. 当我挂载组件时,我想用货币更新默认的当前状态。 2. 当我单击更改我的 id 状态的按钮时,我想发出新的 API 请求(通过 useEffect),然后我再次使用来自 API 的更新货币调用我的状态。
  • 这应该可以,只要确保将 id 更改为与以前的值不同
  • 只有当我直接使用更新状态时才有效:currencies.push(euro, dolar/franc,1/dolar); 而不是setCurrencies(currencies => [...currencies, currencyArray]);
【解决方案2】:

你可以调用 useEffect cb 一个组件挂载:

useEffect(()=>{
 //your code
 // no need for checking for the updates it they are inside the component
 }, []);

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 2020-06-04
    • 1970-01-01
    • 2019-10-07
    • 2019-11-11
    • 2019-04-03
    • 2020-02-22
    • 2022-08-02
    • 1970-01-01
    相关资源
    最近更新 更多