如何解决React“太多重新渲染”错误

时间:2019-09-09 14:39:17

标签: reactjs react-hooks

我正在学习React挂钩,并具有以下代码:

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方法中添加了[]作为第二个参数,我认为这可能会阻止页面不断重新呈现。

有人可以帮忙吗?谢谢!

2 个答案:

答案 0 :(得分:3)

不知道您是否将代码复制到问题的错误位置,但这可以使它变得更好。

  ...
  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>
  );

这会起作用,但同时不好,也许您只想在重奏结束后才增加计数?

所以您可以使用.then

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

答案 1 :(得分:0)

这是不正确的,因为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;