【问题标题】:Loading state in react: Too many re-renders. React limits the number of renders to prevent an infinite loop反应中的加载状态:重新渲染太多。 React 限制渲染次数以防止无限循环
【发布时间】:2020-07-12 08:42:44
【问题描述】:

如何防止出现以下错误:

重新渲染过多。 React 限制了渲染的数量以防止无限循环。'

我的代码:

function App() {
    const [items, setItems] = useState([]);
    const [isLoading, setIsLoading] = useState(true);
    if (items.length == 0) loadMore()
    return <div>
        {isLoading
            ? <div>Loading...</div>
            : <ol>{items.map(i => <li>{i}</li>)}</ol>
        }
        <button disabled={isLoading} onClick={loadMore} style={{ width: "100%" }}>
            {isLoading ? "Loading..." : "Load again"}
        </button>
    </div>;

    function loadMore() {
        setIsLoading(true); // ⚠ errors!
        const uri = "https://www.reddit.com/r/reactjs.json";
        fetch(uri)
            .then(r => r.json())
            .then(r => {
                const newItems = r.data.children.map(i => i.data.title);
                items.push(...newItems);
                setItems([...items]);
                setIsLoading(false);
            });
    }
}

Stackblitz link.

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    我同意@tarek-essam上面的回答

    并添加更多内容,您不能直接在 React 中改变状态...

    将 loadMore() 函数更改为:

        function loadMore() {
            setIsLoading(true);
            const uri = "https://www.reddit.com/r/reactjs.json";
            fetch(uri)
                .then(r => r.json())
                .then(r => {
                    const newItems = r.data.children.map(i => i.data.title);
                    setItems([...items, ...newItems]);
                    setIsLoading(false);
                });
        }
    

    所以完整的解决方案是:

    import React, { Component, useState } from "react";
    import { render } from "react-dom";
    import Hello from "./Hello";
    import "./style.css";
    
    render(<App />, document.getElementById("root"));
    
    function App() {
      const [items, setItems] = useState([]);
      const [isLoading, setIsLoading] = useState(true);
    
      React.useEffect(() => {
        (async () => await loadMore())();
      }, []);
    
      return (
        <div>
          {isLoading ? (
            <div>Loading...</div>
          ) : (
            <ol>
              {items.map(i => (
                <li>{i}</li>
              ))}
            </ol>
          )}
          <button disabled={isLoading} onClick={loadMore}>
            {isLoading ? "Loading..." : "Load again"}
          </button>
        </div>
      );
    
      function loadMore() {
        setIsLoading(true);
        const uri = "https://www.reddit.com/r/vuejs.json"; // using vue js cause reactjs json is not working in my machine ?
        fetch(uri)
          .then(r => r.json())
          .then(r => {
            const newItems = r.data.children.map(i => i.data.title);
            setItems([...items, ...newItems]);
            setIsLoading(false);
          })
          .catch(err => console.log(err));
      }
    }
    

    【讨论】:

      【解决方案2】:

      这是因为if (items.length == 0) loadMore()这个条件。

      因为一开始长度为0,所以调用了loadMore,你设置了状态,你又进入了调用loadMore的条件,以此类推。

      使用 useEffect 钩子和一个空的依赖数组,而不是在组件挂载时调用一次函数的条件。

      useEffect(loadMore, [])
      

      【讨论】:

        猜你喜欢
        • 2021-10-21
        • 2020-09-11
        • 2021-10-20
        • 2020-09-22
        • 2020-04-14
        • 2021-02-26
        • 1970-01-01
        相关资源
        最近更新 更多