我正在尝试在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;
答案 0 :(得分:152)
因为你在render方法中调用toggle会导致重新渲染和切换,会再次调用并重新渲染,等等
您的代码中的这一行
{<td><span onClick={this.toggle()}>Details</span></td>}
您需要onClick
引用this.toggle
而不是调用它
要修复问题,请执行此操作
{<td><span onClick={this.toggle}>Details</span></td>}
答案 1 :(得分:10)
调用函数时应该传递事件对象:
{<td><span onClick={(e) => this.toggle(e)}>Details</span></td>}
如果您不需要处理onClick事件,您也可以输入:
{<td><span onClick={(e) => this.toggle()}>Details</span></td>}
现在您还可以在函数中添加参数。
答案 2 :(得分:4)
在这种情况下,此代码
{<td><span onClick={this.toggle()}>Details</span></td>}
使切换功能立即调用并一次又一次地重新呈现它,从而进行无限次调用。
因此仅将对该切换方法的引用传递给您即可解决此问题。
so
{<td><span onClick={this.toggle}>Details</span></td>}
将是解决方案代码。
如果要使用(),则应使用这样的箭头功能
{<td><span onClick={()=> this.toggle()}>Details</span></td>}
如果要传递参数,则应选择最后一个选项,然后可以传递这样的参数
{<td><span onClick={(arg)=>this.toggle(arg)}>Details</span></td>}
在最后一种情况下,它不会立即调用并且不会导致函数的重新呈现,因此避免了无限调用。
答案 3 :(得分:3)
先忘记反应:
这与反应无关,让我们了解Java Script的基本概念。例如,您已经用Java脚本(名称为A)编写了以下函数。
function a() {
};
问题1:如何调用我们定义的函数?
答:a();
问题2)如何传递函数引用,以便我们可以稍后调用它?
答:让我们开心= a;
现在问您的问题,您已经使用了带有函数名称的括号,这意味着在呈现以下语句时将调用该函数。
<td><span onClick={this.toggle()}>Details</span></td>
然后如何纠正?
简单!!只需删除括号即可。通过这种方式,您已将该函数的引用提供给onClick事件。仅当您单击组件时,它才会回调您的函数。
<td><span onClick={this.toggle}>Details</span></td>
一个建议可以回应:
避免使用某人在答案中建议的内联函数,否则可能会导致性能问题。
避免遵循以下代码,每次调用函数时都会一次又一次创建相同函数的实例(lamda语句每次都会创建新实例)。
注意:无需将事件(e)显式传递给函数。您可以通过函数访问它而无需传递它。
{<td><span onClick={(e) => this.toggle(e)}>Details</span></td>}
https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578
答案 4 :(得分:1)
如果您不需要将参数传递给函数,只需从函数中删除(),如下所示:
<td><span onClick={this.toggle}>Details</span></td>
但如果要传递参数,则应执行以下操作:
<td><span onClick={(e) => this.toggle(e,arg1,arg2)}>Details</span></td>
答案 5 :(得分:1)
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触发,因为这就是您的价值…等等
答案 6 :(得分:1)
我知道这有很多答案,但是由于大多数答案都比较老(好,比较老),所以没有人提到我很快就成长的方法。简而言之:
使用功能组件和挂钩。
以后:
尝试使用尽可能多的功能组件代替类,尤其是用于渲染,并尝试使它们尽可能纯净(是的,默认情况下数据很脏)。
功能组件的两个明显的好处(还有更多):
第二点的快速证明-这不是绝对令人恶心吗?
constructor(props) {
super(props);
this.toggle= this.toggle.bind(this);
this.state = {
details: false
}
}
如果您使用功能组件更多,然后进行渲染,则需要伟大的二重奏的第二部分-钩子。为什么它们比生命周期方法更好,它们还有什么用,还有更多的事情会占用我很多空间,所以我建议您听这个人自己讲:Dan preaching the hooks
在这种情况下,您只需要两个钩子即可:
一个方便命名为useCallback
的回调挂钩。这样,您可以防止在重新渲染时反复绑定功能。
状态钩子,称为useState
,即使整个组件都在起作用并完整执行,状态钩子也可以保持状态(是的,由于钩子的魔力,这是可能的)。在该挂钩中,将存储toggle的值。
如果您读到这一部分,您可能希望看到我在实践中谈论的所有内容并应用于原始问题。干得好: Demo
对于那些只想浏览组件并且WTF就是这样的人,这里是:
const Item = () => {
// HOOKZ
const [isVisible, setIsVisible] = React.useState('hidden');
const toggle = React.useCallback(() => {
setIsVisible(isVisible === 'visible' ? 'hidden': 'visible');
}, [isVisible, setIsVisible]);
// RENDER
return (
<React.Fragment>
<div style={{visibility: isVisible}}>
PLACEHOLDER MORE INFO
</div>
<button onClick={toggle}>Details</button>
</React.Fragment>
)
};
PS:我写这篇文章是为了防止许多人因类似的问题降落在这里。希望他们至少会满意他们所看到的内容,以便对谷歌进行更多搜索。这不是我在说其他答案是错误的,这是我在说自从编写答案以来,还有另一种处理方式(恕我直言,更好的方法)。
答案 7 :(得分:0)
onClick,您应该调用函数,也就是调用函数切换。
onClick={() => this.toggle()}
答案 8 :(得分:0)
1。如果要在调用中传递参数,则需要调用如下方法
由于我们使用箭头函数,因此无需绑定cunstructor
中的方法。
onClick={() => this.save(id)}
当我们像这样在构造函数中绑定方法时
this.save= this.save.bind(this);
然后我们需要调用该方法而不传递任何类似下面的参数
onClick={this.save}
,我们尝试在调用函数时传递参数 如下图所示,那么错误就好像超过了最大深度。
onClick={this.save(id)}