ReactJS : 최대 업데이트 깊이 초과 오류


177

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;

35
변경 this.toggle()this.toggle{()=> this.toggle()}
학습자

8
또 다른 개선, 문제는 무관하지만 :십시오 toggle(){...}toggle = () => {...}당신이 필요가 없습니다 bind그것!
Berry M.

@learner 감사합니다. 당신도 저를 도왔습니다. 솔루션의 이유를 친절하게 설명해 주시겠습니까? 이 둘의 차이점은 무엇입니까?
Shamim

2
@Shamim 기존 함수 호출과 함수에 대한 참조 전달의 차이점입니다. 사용자가 페이지를로드하자마자 트리거되는 코드가 아니라 사용자가 무언가를 수행 할 때 표시되고 트리거되는 코드를 작성하고 있음을 이해하는 것이 도움이됩니다. reactjs.org/docs/faq-functions.html
DisplayName

답변:


274

render 메소드 안에서 토글을 호출하면 다시 렌더링되고 토글이 다시 호출되고 다시 렌더링됩니다.

이 줄은 코드에서

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

당신은 그것을 호출하지 않는 onClick참조 해야 this.toggle합니다

이 문제 를 해결 하려면

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

8
비슷한 상황에 직면하고 있지만 전환하려면 매개 변수를 전달해야합니다.이 작업을 어떻게 수행 할 수 있습니까?
Niveditha Karmegam

58
@NivedithaKarmegam 마십시오 onClick={(param) => this.toggle(param)}. 이것은 즉시 (그리고 다시 렌더링) 실행되지 않습니다. 이것은 콜백 정의입니다 (화살표 함수).
Fabian Picone

15
@FabianPicone은 메소드를 시도했지만 i console.log에서 "param"이 이벤트로 전달되었음을 보여줍니다. 실제로 수행해야합니다onClick={() => this.toggle(param)}
iWillGetBetter

6
@iWillGetBetter 예 onClick의 첫 번째 매개 변수는 클릭 이벤트입니다. 추가 매개 변수가 필요한 경우 전달할 수도 있습니다 onClick={(event) => this.toggle(event, myParam)}.
Fabian Picone

1
이 함수가 closeEditModal = () => this.setState({openEditModal: false});있습니다. 렌더링하는 법?
Nux

31

함수를 호출 할 때 이벤트 객체를 전달해야합니다.

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

onClick 이벤트를 처리 할 필요가없는 경우 다음을 입력 할 수도 있습니다.

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

이제 함수 내에 매개 변수를 추가 할 수도 있습니다.


2
아무것도 지정하지 않으면 이벤트 객체가 자동으로 전송됩니다. 호출 된 함수에 입력 매개 변수 만 포함하십시오.
Jeff Pinkston

2
{<td><span onClick={() => this.toggle(whateverParameter)}>Details</span></td>}나를 위해 트릭을 수행
iWillGetBetter

22

먼저 반응을 잊어라 :
이것은 반응과 관련이 없으며 Java Script의 기본 개념을 이해하도록하자. 예를 들어 Java 스크립트에서 다음 함수를 작성했습니다 (이름은 A).

function a() {

};

Q.1) 정의한 함수를 어떻게 호출합니까?
답변 : a ();

Q.2) 후자를 호출 할 수 있도록 함수 참조를 전달하는 방법은 무엇입니까?
답변 :하자 = a;

이제 당신의 질문에, 당신은 함수 이름과 함께 paranthesis를 사용했습니다. 다음 명령문이 렌더링 될 때 함수가 호출된다는 것을 의미합니다.

<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


6

나는 이것이 많은 답변을 가지고 있음을 알고 있지만 대부분이 오래 되었기 때문에 (매우 오래 됨), 내가 매우 빠르게 성장하는 접근법을 언급하는 사람은 없습니다. 한마디로 :

기능적 구성 요소와 고리를 사용하십시오 .

더 길게 :

특히 렌더링을 위해 클래스 구성 요소 대신 많은 기능 구성 요소를 사용하고 가능한 한 순수하게 유지하십시오 (예, 기본적으로 데이터는 더럽습니다).

기능적 구성 요소의 두 가지 명백한 이점 (더 많음) :

  • 순결 또는 거의 순결은 디버깅을 훨씬 쉽게 만듭니다.
  • 기능적인 구성 요소는 생성자 보일러 코드를 필요로하지 않습니다

2 포인트에 대한 빠른 증거-이것이 역겨운가요?

constructor(props) {
        super(props);     
        this.toggle= this.toggle.bind(this);
        this.state = {
            details: false
        } 
    }  

기능 구성 요소를 더 많이 사용하여 렌더링하는 경우 큰 듀오 후크의 두 번째 부분이 필요합니다. 수명주기 방법보다 나은 이유는 무엇입니까? 다른 방법으로 더 많은 것을 처리 할 공간이 많이 필요하므로 남자 자신의 말을 들어 보는 것이 좋습니다 .Dan the hooks

이 경우 두 개의 후크 만 필요합니다.

편리하게 이름이 지정된 콜백 후크 useCallback. 이렇게하면 다시 렌더링 할 때 함수가 계속 바인딩되는 것을 막을 수 있습니다.

useState전체 구성 요소가 작동하고 전체를 실행하는 데에도 불구하고 상태를 유지하기위한 이라고하는 상태 후크 (예, 후크의 마법 때문에 가능) 해당 후크 내에 토글 값을 저장합니다.

이 부분을 읽으면 아마도 내가 실제로 이야기하고 원래 문제에 적용한 모든 것을보고 싶을 것입니다. 여기 있습니다 : 데모

구성 요소를 한 눈에보고 싶어하는 사용자에게는 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>
  )
};

추신 : 나는 많은 사람들이 비슷한 문제로 여기에 도착하는 경우에 이것을 썼습니다. 바라건대 그들은 적어도 조금 더 구글을 볼 수있을만큼 충분히 좋아하는 것을 좋아할 것입니다. 이것은 다른 답변이 잘못되었다고 말하는 것이 아닙니다. 이것은 그들이 작성된 시간부터 이것을 처리하는 다른 방법 (IMHO, 더 나은 방법)이 있다는 것입니다.


5

함수에 인수를 전달할 필요가 없으면 아래처럼 함수에서 ()를 제거하십시오.

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

그러나 인수를 전달하려면 다음과 같이해야합니다.

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

3

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 함수는 상태를 설정하여 rerender를 발생시킵니다. onDigit가 onClick으로 설정 한 값이기 때문에 onDigit이 실행됩니다.이 경우 상태가 설정되어 rerender가 발생하여 onDigit가 실행됩니다. 다시… 기타


3

1. 호출에서 인수를 전달하려면 아래처럼 메소드를 호출해야합니다. 화살표 함수를 사용하므로에서 메소드를 바인딩 할 필요가 없습니다 cunstructor.

onClick={() => this.save(id)} 

이렇게 생성자에서 메소드를 바인딩 할 때

this.save= this.save.bind(this);

다음과 같은 인수를 전달하지 않고 메소드를 호출해야합니다.

onClick={this.save}

아래와 같이 함수를 호출하는 동안 인수를 전달하려고하면 최대 깊이를 초과 한 것처럼 오류가 발생합니다.

 onClick={this.save(id)}

1

onClick 함수를 호출해야합니다.이를 함수 토글이라고합니다.

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


1

이 경우이 코드

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

토글 기능을 즉시 호출하고 다시 렌더링하여 무한 호출합니다.

따라서 해당 전환 방법에 대한 참조 만 전달하면 문제가 해결됩니다.

그래서

{<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>}

마지막 경우 즉시 호출하지 않고 함수를 다시 렌더링하지 않으므로 무한 호출을 피할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.