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>}
onClick
this.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
goods
API를 사용합니다.
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
'programing' 카테고리의 다른 글
div에 도구 설명 추가 (0) | 2023.01.31 |
---|---|
JavaScript에서 배열 요소 삭제 - 삭제 vs 스플라이스 (0) | 2023.01.31 |
호출 실패 예기치 않은 서버 응답 수정 방법:Android Studio에서 승인되지 않음 (0) | 2023.01.31 |
MySQL/MariaDB 열 값이 다른 열에서 고유합니다. (0) | 2023.01.31 |
JavaScript에서 화살표 키 누름 감지 (0) | 2023.01.31 |