programing

ReactJS: 최대 업데이트 깊이가 오류를 초과했습니다.

firstcheck 2023. 1. 31. 20:57
반응형

ReactJS: 최대 업데이트 깊이가 오류를 초과했습니다.

ReactJS에서 컴포넌트 상태를 전환하려고 하는데 다음과 같은 오류가 나타납니다.

최대 업데이트 깊이를 초과했습니다.이 문제는 컴포넌트가 componentWillUpdate 또는 componentDidUpdate를 반복적으로 호출할 때 발생할 수 있습니다.리액트는 네스트된 업데이트 수를 제한하여 무한 루프를 방지합니다.

내 코드에 무한 루프가 보이지 않는데, 누가 좀 도와줄래?

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;

렌더 메서드 내에서 토글을 호출하면 다시 호출하고 토글하기 때문에 다시 호출하고, 다시 호출하고, 다시 호출하고, 계속 반복하고 있습니다.

당신의 코드로 이 행

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

onClickthis.toggle 않다

문제를 해결하려면 다음과 같이 하십시오.

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

함수를 호출할 때는 event 객체를 전달해야 합니다.

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

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

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

이제 함수 내에 파라미터를 추가할 수도 있습니다.

먼저 반응을 잊으십시오.
이것은 리액션과는 관계가 없으며 Java 스크립트의 기본 개념을 이해할 수 있습니다.예를 들어 자바 스크립트(이름 A)에서 다음 함수를 작성했습니다.

function a() {

};

해야 합니까?Q.1)는 어떻게 해야 합니까?
응답: a();

Q.2) 후자라고 부를 수 있도록 함수의 참조를 전달하려면 어떻게 해야 합니까?
하자 =Ans: = a;

이제 질문입니다만, 함수명과 함께 parantesis를 사용했습니다.즉, 다음 문장이 렌더링될 때 함수가 호출됩니다.

<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

이것이 많은 답을 가지고 있다는 것을 알지만, 대부분은 오래된 것이기 때문에, 아무도 접근법에 대해 언급하지 않습니다. 저는 매우 빨리 좋아하게 됩니다.요컨대:

기능 컴포넌트와 후크를 사용합니다.

더 긴 시간:

특히 렌더링을 위해 클래스 컴포넌트 대신 기능 컴포넌트를 최대한 많이 사용하고 최대한 순수하게 유지합니다(예, 데이터는 기본적으로 더럽습니다).

기능 컴포넌트의 두 가지 분명한 장점(더 많은 장점이 있습니다)

  • 순수도 또는 거의 순수도에 가깝기 때문에 디버깅이 매우 쉬워집니다.
  • 기능성 컴포넌트는 컨스트럭터 보일러 코드의 필요성을 배제합니다.

두 번째 포인트에 대한 빠른 증거 - 이건 정말 역겹지 않나요?

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

렌더링 이상의 기능 컴포넌트를 사용하고 있다면 훌륭한 듀오 훅의 두 번째 부분이 필요합니다.왜 라이프 사이클 방법보다 더 나은지, 그 밖에 무엇을 할 수 있는지, 그리고 훨씬 더 많은 것을 다룰 수 있는 공간이 필요하기 때문에 그 사람의 말을 직접 들어보는 것이 좋습니다.댄이 후크를 설교하다

이 경우 필요한 후크는 2개뿐입니다.

쉽게 '콜백 후크'라고 불립니다.useCallback이렇게 하면 재렌더 시 함수의 바인딩을 반복적으로 방지할 수 있습니다.

으로, 테이트, a, a,, a a a a라고 불립니다.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>
  )
};

PS: 많은 사람들이 비슷한 문제를 안고 이곳에 도착할 경우를 대비해서 이 글을 썼습니다.적어도 구글에서 좀 더 검색해 볼 수 있을 만큼, 제가 보여드린 것을 그들이 좋아하길 바랍니다.다른 답변이 틀렸다고 말하는 것이 아니라, 그 답변이 쓰여진 이후 다른 방법(IMHO, 더 나은 방법)이 있다고 말하는 것입니다.

기능하기 위해 인수를 전달할 필요가 없는 경우 다음과 같이 함수에서 ()를 제거하십시오.

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

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

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

1. 콜에서 인수를 전달하려면 다음과 같은 메서드를 호출해야 합니다.화살표 함수를 사용하고 있기 때문에 메서드를 바인딩할 필요가 없습니다.constructor.

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

이렇게 컨스트럭터에서 메서드를 바인드하면

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

그러면 우리는 아래와 같은 인수를 통과하지 않고 메서드를 호출해야 한다.

onClick={this.save}

그리고 아래와 같이 함수를 호출하면서 인수를 전달하려고 하면 최대 깊이를 초과한 오류가 발생합니다.

 onClick={this.save(id)}

이 경우 이 코드는

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

마지막 경우 즉시 호출되지 않고 함수의 재렌더가 발생하지 않으므로 무한 콜을 회피할 수 있습니다.

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를 발생시키기 때문에 onDigit를 발생시킵니다.이 값은 onClick으로 설정되어 상태를 발생시켜 render를 발생시킵니다.이 값은 바로 onDigit를 발생시키기 때문입니다.기타

클릭 시 함수를 호출해야 합니다.이것은 함수 토글이라고 불립니다.

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

최근에 다음 오류가 발생했습니다.

오류: Miniated Respect error #displays. 전체 메시지를 보려면 https://reactjs.org/docs/error-decoder.html?invariant=185를 방문하거나 전체 오류 및 기타 유용한 경고를 보려면 비miniated dev 환경을 사용하십시오.

방금 발생한 오류의 전문은 다음과 같습니다.

최대 업데이트 깊이를 초과했습니다.이 문제는 컴포넌트가 setState inside를 반복적으로 호출할 때 발생할 수 있습니다.componentWillUpdate또는componentDidUpdate. 리액트는 네스트된 업데이트 수를 제한하여 무한 루프를 방지합니다.

네, 제 경우는 리액트 기능 성분 + 리액트 훅을 사용합니다.먼저 잘못된 샘플 코드를 확인합니다.

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

service- API 호출을 처리하며, DTO 데이터 뷰 모델을 변환하는 방법이 있습니다.리액트랑은 아무 상관 없어프로젝트에 이런 서비스가 있을지도 몰라요.

는...banners goodsAPI를 사용합니다.

useEffect({...}, [info, goods])에는 두 종속성이 . 즉, 에는 두 가지 종속성이 있습니다.info ★★★★★★★★★★★★★★★★★」goods.

info ★★★★★★★★★★★★★★★★★」goods 변화하다,useEffect훅이 재투입되어 배너 뷰 모델을 설정합니다.★★★★★★★★★★★★★★★★★?

! 메모리 누수가 생길 거야useEffect왜은무무무실실실겁겁??????왜?

★★★★★★★★★★★★★★★★★★★★시setBanner()되고 "Component"가재실행됩니다.const info = service.makeInfo(goods);스테이트먼트가 다시 실행되고 새 오브젝트가 반환됩니다.이것에 의해, 이 스테이트먼트는useEffect의 : " " ", "useEffect데드 사이클을 형성하면서 다시 실행할 수 있습니다.

해결 방법: use는 기억된 값을 반환합니다.이 기억된 값을 의 의존관계로 사용합니다.useEffect

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

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

//... 

코드앤드박스

좋은 답변은 많지만 리액트 후크를 고려했을 때 모두 몇 가지 예를 놓쳤다/리액트 네이티브

위의 답변에서 설명한 바와 같이 콜백은 자 컴포넌트 내에서 "호출"되지 않고 참조만 해야 합니다.

이게 무슨 뜻이죠?프레스로 색상을 변경하기 위해 RGB 색상을 변경하는 2개의 자성 컴포넌트를 사용하는 부모 컴포넌트에 대해 생각해 보겠습니다.

import React, { useState } from "react"
import {View, Text, StyleSheet } from "react-native"
import ColorCounter from "../components/ColorCounter"

const SquareScreen = () =>{
  const [red, setRed] = useState(0)
  const [blue, setBlue] = useState(0)
  const [green, setGreen] = useState(0)

 return (
   <View>
     <ColorCounter 
       onIncrease={() => setRed(red + 15)}
       onDecrease={() => setRed(red - 15)}
       color="Red"
     />
     <ColorCounter 
       onIncrease={() => setBlue(blue + 15)}
       onDecrease={() => setBlue(blue - 15)} 
       color="Blue" 
     />
     <ColorCounter 
       onIncrease={() => setGreen(green + 15)}
       onDecrease={() => setGreen(green - 15)}
       color="Green" 
     />
    <View 
      style={{ 
        height:150,
        width:150, 
        backgroundColor:`rgb(${red},${blue},${green})`
      }}
    />
    </View>
 )   
}

const styles = StyleSheet.create({})

export default SquareScreen

이것은 아동 버튼의 컴포넌트입니다.

import React, { useState } from "react"
import {View, Text, StyleSheet, Button } from "react-native"

const ColorCounter = ({color, onIncrease, onDecrease}) =>{
  return (
    <View>
      <Text>{color}</Text>
      <Button onPress={onIncrease}  title={`Increase ${color}`} /> --> here if you use onPress={onIncrease()} this would cause a call of setColor(either setRed,SetBlue or setGreen) that call again onIncrease and so on in a loop)
      <Button onPress={onDecrease}  title={`Decrease ${color}`} />
    </View>  
  )  
}

export default ColorCounter

과 같은 useEffect가 .useEffect(() =>{}) 요.이렇게useEffect(() => {},[]).

언급URL : https://stackoverflow.com/questions/48497358/reactjs-maximum-update-depth-exceeded-error

반응형