我试图在ReactJS中切换组件的状态,但我得到一个错误说明:

超过最大更新深度。当组件在componentWillUpdate或componentDidUpdate中反复调用setState时,就会发生这种情况。React限制了嵌套更新的数量,以防止无限循环。

我在我的代码中没有看到无限循环,有人能帮我吗?

ReactJS组件代码:

import React, { Component } from 'react';
import styled from 'styled-components';

class Item extends React.Component {
    constructor(props) {
        super(props);     
        this.toggle= this.toggle.bind(this);
        this.state = {
            details: false
        } 
    }  
    toggle(){
        const currentState = this.state.details;
        this.setState({ details: !currentState }); 
    }

    render() {
        return (
            <tr className="Item"> 
                <td>{this.props.config.server}</td>      
                <td>{this.props.config.verbose}</td> 
                <td>{this.props.config.type}</td>
                <td className={this.state.details ? "visible" : "hidden"}>PLACEHOLDER MORE INFO</td>
                {<td><span onClick={this.toggle()}>Details</span></td>}
            </tr>
    )}
}

export default Item;

当前回答

在我的例子中,这是由于无限循环。

我的一个函数是设置状态,组件正在重新加载,该组件依次导致函数重新运行,然后函数再次设置状态。这个循环一直到无穷。

为了避免这种情况,我把我的函数包装在useEffect钩子中,并给它一些依赖,这样这个函数只在依赖被改变时运行。

其他回答

onClick你应该调用函数,这叫做你的函数切换。

onClick={() => this.toggle()}

你应该在调用函数时传递事件对象:

{<td><span onClick={(e) => this.toggle(e)}>Details</span></td>}

如果你不需要处理onClick事件,你也可以输入:

{<td><span onClick={(e) => this.toggle()}>Details</span></td>}

现在还可以在函数中添加参数。

ReactJS:最大更新深度超过错误

inputDigit(digit){
  this.setState({
    displayValue: String(digit)
  })

<button type="button"onClick={this.inputDigit(0)}>

为什么呢?

<button type="button"onClick={() => this.inputDigit(1)}>1</button>

onDigit函数设置状态,这将导致再现 导致onDigit触发,因为那是你设置的值 onClick使状态被设置,从而引起渲染, 这会导致onDigit触发,因为那是你的值。等等

在我的例子中,这是由于无限循环。

我的一个函数是设置状态,组件正在重新加载,该组件依次导致函数重新运行,然后函数再次设置状态。这个循环一直到无穷。

为了避免这种情况,我把我的函数包装在useEffect钩子中,并给它一些依赖,这样这个函数只在依赖被改变时运行。

最近我得到了这个错误:

错误:迷你反应错误#185;访问https://reactjs.org/docs/error-decoder.html?invariant=185获取完整消息,或者使用非简化的开发环境获取完整错误和其他有用警告。

您刚刚遇到的错误的全文如下:

超过最大更新深度。当组件在componentWillUpdate或componentDidUpdate中反复调用setState时,就会发生这种情况。React限制了嵌套更新的数量,以防止无限循环。

好的。这是我的案例,我使用react函数组件+ react钩子。让我们先看看错误的示例代码:

import { useEffect, useState } from "react";
const service = {
  makeInfo(goods) {
    if (!goods) return { channel: "" };
    return { channel: goods.channel };
  },
  getGoods() {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve({
          channel: "so",
          id: 1,
          banners: [{ payway: "visa" }, { payway: "applepay" }]
        });
      }, 1000);
    });
  },
  makeBanners(info, goods) {
    if (!goods) return [];
    return goods.banners.map((v) => {
      return { ...v, payway: v.payway.toUpperCase() };
    });
  }
};
export default function App() {
  const [goods, setGoods] = useState();
  const [banners, setBanners] = useState([]);

  useEffect(() => {
    service.getGoods().then((res) => {
      setGoods(res);
    });
  }, []);

  const info = service.makeInfo(goods);

  useEffect(() => {
    console.log("[useEffect] goods: ", goods);
    if (!goods) return;
    setBanners(service.makeBanners({}, goods));
  }, [info, goods]);

  return <div>banner count: {banners.length}</div>;
}

服务过程API调用,并有一些方法转换DTO数据视图模型。这与React无关。也许你的项目中有这样的服务。

我的逻辑是,横幅视图模型是从API返回的商品数据构建的。

useEffect({…}, [info, goods])有两个依赖项:info和goods。

当info和goods发生变化时,useEffect钩子将重新执行,设置横幅视图模型,看起来不错,对吧?

不!这将导致内存泄漏。useEffect钩子将无限地执行。为什么?

因为当setBanner()执行时,组件将重新呈现,const info = service.makeInfo(goods);语句将再次执行,返回一个新的info对象,这将导致useEffect的deps改变,导致useEffect再次执行,形成一个死循环。

解决方案:使用useMemo返回一个记忆值。使用这个记忆值作为useEffect钩子的依赖项。

// ...
 const info = useMemo(() => {
    return service.makeInfo(goods);
  }, [goods]);

  useEffect(() => {
    console.log("[useEffect] goods: ", goods);
    if (!goods) return;
    setBanners(service.makeBanners({}, goods));
  }, [info, goods]);

//... 

Codesandbox