Maj*_*olm 119 javascript reactjs react-native
我试图在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;
Run Code Online (Sandbox Code Playgroud)
Ali*_*Ali 207
因为你在render方法中调用toggle会导致重新渲染和切换,会再次调用并重新渲染,等等
你的代码中的这一行
{<td><span onClick={this.toggle()}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
你需要onClick提到this.toggle不要叫它
要解决这个问题做到这一点
{<td><span onClick={this.toggle}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
小智 17
您应该在调用函数时传递事件对象:
{<td><span onClick={(e) => this.toggle(e)}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
如果您不需要处理onClick事件,您还可以键入:
{<td><span onClick={(e) => this.toggle()}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
现在您还可以在函数中添加参数.
Piy*_*h N 14
首先,忘记反应:
这与反应无关,让我们了解Java Script的基本概念。例如,您已经用Java脚本(名称为A)编写了以下函数。
function a() {
};
Run Code Online (Sandbox Code Playgroud)
Q.1)如何调用我们定义的函数?
答:a();
Q.2)如何传递函数的引用,以便我们可以稍后调用它?
答:让我们开心吧= a;
现在来问您的问题,您已经在函数名称中使用了括号,这意味着在呈现以下语句时将调用该函数。
function a() {
};
Run Code Online (Sandbox Code Playgroud)
那么如何纠正呢?
简单!!只需删除括号即可。通过这种方式,您已将该函数的引用提供给onClick事件。仅当单击组件时,它才会回调函数。
<td><span onClick={this.toggle()}>Details</span></td>Run Code Online (Sandbox Code Playgroud)
一个建议可以做出反应:
避免像别人在回答中建议的那样使用内联函数,否则可能会导致性能问题。避免遵循以下代码,每次调用函数时都会一次又一次创建相同函数的实例(lamda语句每次都会创建新实例)。
注意:无需将事件(e)显式传递给函数。您可以在函数中访问它而无需传递它。
<td><span onClick={this.toggle}>Details</span></td>Run Code Online (Sandbox Code Playgroud)
https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578
Dan*_*ith 13
我知道这有很多答案,但由于它们中的大多数都是旧的(好吧,旧的),没有提到我非常喜欢的方法。简而言之:
使用功能组件和钩子。
在更长的时间:
尝试使用尽可能多的功能组件而不是类组件,特别是用于渲染,并尽量保持它们的纯净(是的,我知道默认情况下数据是脏的)。
功能组件有两个显而易见的好处(还有更多):
快速证明第二点 - 这不是绝对恶心吗?
constructor(props) {
super(props);
this.toggle= this.toggle.bind(this);
this.state = {
details: false
}
}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用功能组件进行渲染,那么您将需要伟大的二人组的第二部分 - 钩子。为什么它们比生命周期方法更好,它们还能做什么等等会占用我很多篇幅,所以我建议你听听他本人的声音:Dan 讲授钩子
在这种情况下,您只需要两个钩子:
方便地命名的回调钩子useCallback。这样您就可以防止在重新渲染时一遍又一遍地绑定函数。
一个状态钩子,称为useState,用于保持状态,尽管整个组件都在运行并完整地执行(是的,由于钩子的魔力,这是可能的)。在该钩子中,您将存储 toggle 的值。
如果你读到这部分,你可能想看到我在行动中谈到并应用于原始问题的所有内容。给你: 演示
对于那些只想看一眼组件和 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>
)
};
Run Code Online (Sandbox Code Playgroud)
PS:我写这个是为了防止很多人遇到类似问题。希望他们会喜欢我在这里展示的内容,至少足以让他们多用谷歌搜索一下。这不是我说其他答案是错误的,这是我说自从它们被编写以来,有另一种方法(恕我直言,更好的方法)来处理这个问题。
如果您不需要将参数传递给函数,只需从函数中删除 (),如下所示:
<td><span onClick={this.toggle}>Details</span></td>
Run Code Online (Sandbox Code Playgroud)
但是如果你想传递参数,你应该像下面这样:
<td><span onClick={(e) => this.toggle(e,arg1,arg2)}>Details</span></td>
Run Code Online (Sandbox Code Playgroud)
小智 5
1.如果我们想在调用中传递参数,那么我们需要调用如下方法因为我们使用箭头函数不需要绑定方法 constructor 。
onClick={() => this.save(id)}
Run Code Online (Sandbox Code Playgroud)
当我们像这样在构造函数中绑定方法时
this.save= this.save.bind(this);
Run Code Online (Sandbox Code Playgroud)
然后我们需要在不传递任何参数的情况下调用该方法,如下所示
onClick={this.save}
Run Code Online (Sandbox Code Playgroud)
并且我们尝试在调用函数时传递参数,如下所示,然后错误就像超出了最大深度。
onClick={this.save(id)}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,此代码
{<td><span onClick={this.toggle()}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
导致切换函数立即调用并一次又一次地重新渲染,从而进行无限调用。
所以只传递对该切换方法的引用将解决问题。
所以 ,
{<td><span onClick={this.toggle}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
将是解决方案代码。
如果你想使用 () ,你应该使用这样的箭头函数
{<td><span onClick={()=> this.toggle()}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
如果你想传递参数,你应该选择最后一个选项,你可以像这样传递参数
{<td><span onClick={(arg)=>this.toggle(arg)}>Details</span></td>}
Run Code Online (Sandbox Code Playgroud)
在最后一种情况下,它不会立即调用并且不会导致函数的重新渲染,从而避免了无限调用。
| 归档时间: |
|
| 查看次数: |
145446 次 |
| 最近记录: |