【问题标题】:How to solve React "too many re-renders" error如何解决 React “太多重新渲染”错误
【发布时间】:2019-09-09 14:39:17
【问题描述】:

我正在学习 React hooks 并且有以下代码:

import React, { useState, useEffect } from "react";
import "./App.css";

function App() {

  const [count, setCount] = useState(0);
  const [person, setPerson] = useState([]);

  useEffect(() => {
    getPerson();
  }, []);

  const getPerson = async () => {
    const response = await fetch("https://api.randomuser.me");
    const data = await response.json();
    setPerson(data.results);
  };

  return (
    <div className="App">
      <p>You clicked {count} times</p>
      <button onClick={() => getPerson(), setCount(count + 1)}>Click Me</button>
      <div>{person.map(person => person.name.first)}</div>
    </div>
  );
}

export default App;

当我单击“单击我”按钮时,我希望更新计数器并调用 API 以获取随机人。单独地,这两个代码都可以工作。但是,当我尝试同时执行这两项操作时,我收到此错误:Too many re-renders. React limits the number of renders to prevent an infinite loop.

我是 React 新手,不知道为什么会这样。我在 UseEffect 方法中添加了[] 作为第二个参数,我认为这可能会阻止页面不断重新渲染。

有人可以帮忙吗?谢谢!

【问题讨论】:

  • 我认为您有语法错误? onClick={() =&gt; getPerson(), setCount(count + 1)}

标签: reactjs react-hooks


【解决方案1】:

不确定您是否将代码错误地复制到您的问题中,但这里有一些可以让它变得更好的东西。

  ...
  return (
    <div className="App">
      <p>You clicked {count} times</p>
      <button onClick={() => { getPerson(); setCount(count + 1)}}>Click Me</button>
      <div>{person.map(person => person.name.first)}</div>
    </div>
  );

这会起作用,但同时也不好,也许您只想在 resquet 完成时才增加计数?

所以你可以做的是使用.then

onClick={() => { getPerson().then(() => setCount(count + 1))}}

【讨论】:

  • 非常感谢@vencovsky :) 你介意告诉我为什么使用 .then 更好吗?
  • @juemura7 和.thensetCount 只会在getPerson 完成时执行,这意味着只有在对 api 的请求返回并且您调用 setPerson(data.results) 之后才会执行。如果你不使用.then,用户可以点击很多次,计数器会更新,但是setPerson(data.results)永远不能被调用(因为一些错误或者因为用户互联网太慢)。没有.then 没有问题,但是有了它,计数器将与数据同步。
【解决方案2】:

这是不正确的,因为useEffect 只是类似于componentDidMountcomponentDidUpdate。如果您在此方法中更新状态而不限制它,则会导致无限渲染。

import React, { useState, useEffect } from "react";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);
  const [person, setPerson] = useState([]);

  useEffect(() => {
    // You need to restrict it at some point
    // This is just dummy code and should be replaced by actual
    if (person.length === 0) {
        getPerson();
    }
  }, []);

  const getPerson = async () => {
    const response = await fetch("https://api.randomuser.me");
    const data = await response.json();
    setPerson(data.results);
  };

  return (
    <div className="App">
      <p>You clicked {count} times</p>
      <button onClick={() => {getPerson(); setCount(count + 1);}}>Click Me</button>
      <div>{person.map(person => person.name.first)}</div>
    </div>
  );
}

export default App;

【讨论】:

  • 谢谢@MilindAgrawal :) if (person.length === 0) 有必要吗?代码在没有这一行的情况下工作,想知道是否需要它?
  • 不,它不是真正需要的,可以删除。抱歉回复晚了。
猜你喜欢
  • 2021-03-07
  • 2022-12-31
  • 2020-11-27
  • 2021-11-21
  • 2022-11-27
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
相关资源
最近更新 更多