useEffect Hook 예제:재렌더의 원인은 무엇입니까?
use Effect로 인해 재렌더가 발생하는 시기를 파악 중입니다.저는 다음 예제의 결과에 매우 놀랐습니다.
https://codesandbox.io/embed/romantic-sun-j5i4m
function useCounter(arr = [1, 2, 3]) {
const [counter, setCount] = useState(0);
useEffect(() => {
for (const i of arr) {
setCount(i);
console.log(counter);
}
}, [arr]);
}
function App() {
useCounter();
console.log("render");
return <div className="App" />;
}
이 예의 결과는 다음과 같습니다.
이유는 모르겠지만:
- 는 3번 ).
setCount
첫 - + 1회 - 4회) - 카운터에는 0과 3의 2가지 값밖에 없습니다.이 글에서 설명한 바와 같이 모든 렌더는 자신의 상태와 버팀목을 인식하기 때문에 루프 전체가 각 상태를 상수(1, 2, 3)로 하여 실행됩니다.-> 하지만 왜 상태는 2가 되지 않는 것일까요?
나는 무슨 일이 일어나고 있는지 설명하는데 최선을 다할 것이다.7번과 10번 두 가지 가정도 하고 있습니다.
- 앱 구성 요소가 마운트됩니다.
useEffect
마운트 후 호출됩니다.useEffect
를 ' '저장'합니다counter
0으로 하다- 3번입니다. 반복 " " "
setCount
에 카운터가 는 'syslog' 0.100입니다이 카운터는 'syslog' 버전에 따라0 입니다.0으로 3으로 3으로 3으로 하다상태가 변화했기 때문에(0 -> 1, 1 -> 2, 2 -> 3) 플래그와 같은 리액트세트를 리액터 합니다. - 중 도 다시 .
useEffect
.useEffect
재검출이 완료됩니다. - ''가
useEffect
가 " " ", " "의 합니다.counter
앱 실행 중에 변경되었으므로 앱을 다시 렌더링합니다. - 와 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」
useCounter
시시시호호호다다.useCounter
커스텀 훅추정:저도 몰랐습니다만, 디폴트 파라미터가 다시 작성되거나 적어도 React가 새로운 파라미터라고 생각하게 되는 것 같습니다. 따라서 가 신규로 인식되기 때문에 후크는 다시 실행됩니다. 이것이 제가 두 번째 실행을 설명할 수 있는 유일한 이유입니다. - 의 두 중
useEffect
, . . . . . . . .counter
3면 되다.따라서 콘솔로그는 예상대로 숫자 3을 3회 기록합니다. -
useEffect
실행 중 카운터가 변경(3 -> 1, 1 -> 2, 2 -> 3)된 것을 React가 발견하면 앱이 다시 렌더링되어 세 번째 '렌더' 로그가 발생합니다. - 추정: 입니다.
useCounter
의 관점에서 이 간에 , 그 하지 않기 에 훅은 이전 렌더와 변경되지 않았습니다. 따라서 훅은 앱 내부에서 코드를 실행하지 않습니다.useEffect
을 사용하다따라서 앱의 첫 번째 렌더링에서는 항상 후크 코드가 실행됩니다.에서는 후크의 .counter
하고, , 을 하지 합니다.0부터 3까지 재실행을 결정하고, 앱이 내부 상태를 세 번째로 확인한 것은 3이었고, 아직 3이므로 재실행을 하지 않습니다.그게 내가 훅을 다시 뛰지 못하게 하는 가장 좋은 이유야.후크 자체에 로그를 삽입하여 세 번째 실행에 영향을 주지 않도록 할 수 있습니다.
이것이 내가 보는 현상입니다.이것으로 좀 더 명확해졌으면 좋겠습니다.
리액트 문서에서 세 번째 렌더링에 대한 설명을 찾았습니다.이렇게 하면 react가 효과를 적용하지 않고 세 번째 렌더링을 하는 이유를 알 수 있다고 생각합니다.
상태 후크를 현재 상태와 동일한 값으로 업데이트하면 React는 하위 렌더링이나 부팅 효과 없이 중단됩니다(React는 Object.is 비교 알고리즘을 사용합니다).
React는 구제하기 전에 특정 컴포넌트를 다시 렌더링해야 할 수 있습니다.리액트는 불필요하게 트리 안으로 "빠져" 들어가지 않기 때문에 걱정할 필요가 없습니다.렌더링 중에 비싼 계산을 할 경우 useMemo를 사용하여 최적화할 수 있습니다.
useState와 useReducer는 이 구제 논리를 공유하고 있는 것 같습니다.
setState 및 이와 유사한 후크는 컴포넌트를 즉시 다시 렌더링하지 않습니다.업데이트를 배치하거나 나중에 연기할 수 있습니다.그럼 가장 최근에 렌더를 하나 받을 수 있는 거네요setCount
counter === 3
.
에는 첫음음 음음음 you you음음음음 with with with 。counter === 0
2개의 와 2개의 리렌더로 구성되어 있습니다.counter === 3
왜 무한루프가 안 되는지 모르겠어요. arr = [1, 2, 3]
는, 어레이를 해, 「이러한 어레이」를 트리거 할 가 있습니다.useEffect
:
- 세트 " " " "
counter
로로 합니다.0
useEffect
「」0
「」, 「」를 설정합니다.counter
로로 합니다.3
.- 입니다.
counter === 3
useEffect
「」3
「」, 「」를 설정합니다.counter
로로 합니다.3
★★★★★★★★★★★★★★★★-
리액트는 여기서 정지하거나 스텝3부터 무한 루프에 도달합니다.
원래 호에서 혼동을 일으킬 수 있는 우연이 있다.과 3개의 렌더링이 useCounter
에는 3과 같은 길이의 기본 파라미터가 있습니다.아래를 보면 더 큰 배열의 경우에도 렌더링이 3개뿐이라는 것을 알 수 있습니다.
function useCounter(arr = [1, 2, 3, 4 , 5 , 6]) {
const [counter, setCount] = React.useState(0);
React.useEffect(() => {
for (const i of arr) {
setCount(i);
console.log(counter);
}
}, [arr]);
}
function App() {
useCounter();
console.log("render");
return <div className = "App" / > ;
}
ReactDOM.render( <App /> ,
document.getElementById("root")
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>
다른 수 .setState
첫 번째 값을 제외하고 매번 동일한 값(배열의 마지막 값)으로 호출되므로 렌더가 사실상 취소됩니다., ' '의 경우,setState
는 다른 루프를 : ) 。
번 걸러서render
를 useEffect
때문에, 「」가 됩니다.setSate
때문에, 「」가 됩니다.render
때문에, 「」가 됩니다.useEffect
기타 등등.
이게 누군가에게 더 명확해졌으면 좋겠어요.
위의 솔루션은 코드에서 무슨 일이 일어나고 있는지 매우 많이 설명했습니다.커스텀 훅에서 default 인수를 사용하여 재렌더를 회피하는 방법을 찾고 있는 경우.이것은 가능한 해결책입니다.
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const defaultVal = [1, 2, 3];
function useCounter(arr = defaultVal) {
const [counter, setCount] = useState(0);
useEffect(() => {
console.log(counter);
setCount(arr);
}, [counter, arr]);
return counter;
}
function App() {
const counter = useCounter();
console.log("render");
return (
<div className="App">
<div>{counter}</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
: 인 상수 값을 사용합니다.defaultVal
,, ,, ,,arr
참조는 항상 동일합니다.되지 않았기 .useEffect는 useEffect를 트리거하지 않습니다.
이 질문과 제가 읽은 모든 답변은 useEffect와 useState 훅을 더 잘 이해할 수 있는 매우 통찰력이 있었습니다.왜냐하면 이러한 훅을 깊이 이해하기 위해 자세히 조사해야 했기 때문입니다.
@ApplePearPerson의 답변은 매우 명료하지만, 몇 가지 잘못된 측면이 있다고 생각합니다.몇 가지 예를 들어 설명하겠습니다.
컴포넌트가 렌더링되므로 콘솔의 첫 번째 "렌더"가 됩니다.
UseEffect는 첫 번째 렌더링 후에 항상 하나 이상 실행됩니다.이것은 기본적으로 두 번째 렌더링에 대한 설명이며 첫 번째 0 x (카운터의 초기 값)를 인쇄하는 이유에 대한 까다로운 부분입니다.
useState 훅의 두 번째 인수는 비동기 함수입니다.따라서 비동기 바하비어는 다른 코드가 실행되기를 대기하기 때문에 블록 내 가 실행되기를 기다립니다.
따라서 for in block은 실행되므로 다음과 같습니다.
나는 1에서 3까지 가서 3의 피니시 값을 갖는다.
이 시점에서 setCount 카운터를 0 t0 3에서 변경합니다.
두 번째 인수로 어레이가 있는 경우 종속성에 대한 사용효과는 변경되므로 이 경우 포함되지 않은 경우에도 Eslint 경고에서도 알 수 있듯이 setCount에서 변경된 카운터 상에서 실행됩니다(React Hook useEffect에는 의존관계가 누락되어 있습니다).
훅에 대한 useState 변경 상태의 원인(이 때문에 useRef가 원인 재렌더 없이 change dom 요소에 대해 도입된 것입니다)이 클래스의 setState에 대해서는 항상 해당되지 않습니다(다만, 이것은 다른 토픽입니다.
마지막 렌더는 각 렌더에 대해 ApplePearPerson이 "알림"을 다시 작성하지만 컴포넌트가 다시 렌더링되기 때문에 완전히 새로운 배열이지만 카운터는 3이고 마지막 값(정확히 3), 즉 useEffect는 다시 실행되지 않습니다.
이 스크린샷은 요약을 시각화하는 데 도움이 됩니다.
예를 들어 for를 for in으로 변경하면 어레이의 키(문자열)를 가져오면 이 경우 카운터의 마지막 값은 2가 됩니다.
https://codesandbox.io/s/kind-surf-oq02y?file=/src/App.js
앞서 설정한 두 번째 카운터를 추가하여 다른 테스트를 수행할 수 있습니다.이 경우 count2가 1 use effect 뒤에 있고 0에서3으로 변경되면 마지막 렌더가 트리거되지만 마지막 useEffect 실행은 트리거되지 않습니다.
요약하려면:
렌더에는 3가지가 있습니다.
첫 번째 이유는 컴포넌트 첫 번째 마운트 때문입니다.
두 번째는 첫 번째 렌더 후에 useEffect가 실행되기 때문입니다.
세 번째는 의존 관계가 0에서 3으로 변경되기 때문입니다.
https://codesandbox.io/s/kind-surf-oq02y?file=/src/App.js:362-383
언급URL : https://stackoverflow.com/questions/56599583/useeffect-hook-example-what-causes-the-re-render
'programing' 카테고리의 다른 글
플러그인 제목 이름 변경 방법> Wordpress > Dashboard (0) | 2023.03.22 |
---|---|
Android에서 Json 어레이 읽기 (0) | 2023.03.22 |
create-react-app에서 제공하는 ESLint 사용 안 함 (0) | 2023.03.22 |
AngularJS: 한 페이지 응용 프로그램에서 인증을 사용하는 기본 예 (0) | 2023.03.22 |
Oracle: 보류 중인 트랜잭션이 있는지 확인하려면 어떻게 해야 합니까? (0) | 2023.03.22 |