request Animation Frame과 cancel Animation Frame을 사용할 때 use Effect 실행 순서와 내부 정리 로직은 무엇입니까?
문서에 , 액액 according according according according 。useEffect
는, 「 로직」을 하고 , 「Clean-up 」을 재실행합니다.useEffect
syslog.syslog.
이펙트가 함수를 반환할 경우 React는 정리할 시간이 되면 해당 기능을 실행합니다.
.왜냐하면 업데이트 처리에는 특별한 코드가 없습니다.
useEffect
는 디폴트로 그것들을 처리합니다.다음 효과를 적용하기 전에 이전 효과를 청소합니다.
, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」requestAnimationFrame
★★★★★★★★★★★★★★★★★」cancelAnimationFrame
에 inside inside inside useEffect
Animation 하지 않을 수 cancel Animation Frame은 애니메이션 프레임을 취소합니다.때로는 오래된 애니메이션이 아직 존재하지만 다음 효과로 인해 다른 애니메이션이 생겨 웹 앱 성능 문제가 발생할 수 있습니다(특히 무거운 DOM 요소를 렌더링해야 할 경우).
하기 전에, 리액트 훅이 몇 의 취소 잘 하지 않게 .이것에 의해, 제 취소 애니메이션 부분이 제대로 동작하지 않게 됩니다.useEffect
상태 변수를 잠그기 위해 폐쇄와 같은 것을 할 수 있습니까?
useEffect의 실행 순서와 내부 정리 로직은 무엇입니까?cancel Animation Frame이 완벽하게 동작하지 않는 아래에 기재되어 있는 코드에 문제가 있습니까?
감사해요.
//import React, { useState, useEffect } from "react";
const {useState, useEffect} = React;
//import ReactDOM from "react-dom";
function App() {
const [startSeconds, setStartSeconds] = useState(Math.random());
const [progress, setProgress] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setStartSeconds(Math.random());
}, 1000);
return () => clearInterval(interval);
}, []);
useEffect(
() => {
let raf = null;
const onFrame = () => {
const currentProgress = startSeconds / 120.0;
setProgress(Math.random());
// console.log(currentProgress);
loopRaf();
if (currentProgress > 100) {
stopRaf();
}
};
const loopRaf = () => {
raf = window.requestAnimationFrame(onFrame);
// console.log('Assigned Raf ID: ', raf);
};
const stopRaf = () => {
console.log("stopped", raf);
window.cancelAnimationFrame(raf);
};
loopRaf();
return () => {
console.log("Cleaned Raf ID: ", raf);
// console.log('init', raf);
// setTimeout(() => console.log("500ms later", raf), 500);
// setTimeout(()=> console.log('5s later', raf), 5000);
stopRaf();
};
},
[startSeconds]
);
let t = [];
for (let i = 0; i < 1000; i++) {
t.push(i);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<text>{progress}</text>
{t.map(e => (
<span>{progress}</span>
))}
</div>
);
}
ReactDOM.render(<App />,
document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0-alpha.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0-alpha.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
위의 답변에서 명확하지 않은 것은 여러 컴포넌트가 혼합되어 있을 때 효과가 실행되는 순서입니다.우리는 useContext를 통해 부모와 자녀의 코디네이션이 필요한 작업을 해왔기 때문에 순서가 더 중요합니다. useLayoutEffect
★★★★★★★★★★★★★★★★★」useEffect
이 점에 있어서, 다른 방법으로 작업합니다.
useEffect
는 다음 컴포넌트(깊이 먼저)로 이동하여 동일한 작업을 수행하기 전에 정리 및 새로운 효과를 수행합니다.
useLayoutEffect
는 각 컴포넌트의 청소(심도 우선)를 실행한 후 모든 컴포넌트의 새로운 효과(심도 우선)를 실행합니다.
render parent
render a
render b
layout cleanup a
layout cleanup b
layout cleanup parent
layout effect a
layout effect b
layout effect parent
effect cleanup a
effect a
effect cleanup b
effect b
effect cleanup parent
effect parent
const Test = (props) => {
const [s, setS] = useState(1)
console.log(`render ${props.name}`)
useEffect(() => {
const name = props.name
console.log(`effect ${props.name}`)
return () => console.log(`effect cleanup ${name}`)
})
useLayoutEffect(() => {
const name = props.name
console.log(`layout effect ${props.name}`)
return () => console.log(`layout cleanup ${name}`)
})
return (
<>
<button onClick={() => setS(s+1)}>update {s}</button>
<Child name="a" />
<Child name="b" />
</>
)
}
const Child = (props) => {
console.log(`render ${props.name}`)
useEffect(() => {
const name = props.name
console.log(`effect ${props.name}`)
return () => console.log(`effect cleanup ${name}`)
})
useLayoutEffect(() => {
const name = props.name
console.log(`layout effect ${props.name}`)
return () => console.log(`layout cleanup ${name}`)
})
return <></>
}
이 세 줄의 코드를 컴포넌트에 넣으면 우선순위가 표시됩니다.
useEffect(() => {
console.log('useEffect')
return () => {
console.log('useEffect cleanup')
}
})
window.requestAnimationFrame(() => console.log('requestAnimationFrame'))
useLayoutEffect(() => {
console.log('useLayoutEffect')
return () => {
console.log('useLayoutEffect cleanup')
}
})
useLayoutEffect > requestAnimationFrame > useEffect
있는 는 바로 이 문제로 인한 입니다.loopRaf
에 다른 useEffect
행됩니니다다
, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★,useLayoutEffect
앞에는 요.requestAnimationFrame
그리고 그 정리기능이 다음 실행 전에 호출되어 중복이 방지된다.
바꾸다
useEffect
로.useLayoutEffect
그러면 문제가 해결될 거야
useEffect
그리고.useLayoutEffect
코드에 표시되는 순서대로 호출됩니다.useState
콜을 클릭합니다.
다음 행을 실행하면 이를 확인할 수 있습니다.
useEffect(() => {
console.log('useEffect-1')
})
useEffect(() => {
console.log('useEffect-2')
})
useLayoutEffect(() => {
console.log('useLayoutEffect-1')
})
useLayoutEffect(() => {
console.log('useLayoutEffect-2')
})
후크를 사용할 때와 라이프 사이클 기능을 실장할 때 주의해야 할 후크는 2종류가 있습니다.
문서에 따르면:
useEffect
react 후에 실행되며 컴포넌트를 렌더링하여 효과 콜백이 브라우저 페인팅을 차단하지 않도록 합니다.이것은 클래스 컴포넌트의 동작과 다릅니다.componentDidMount
그리고.componentDidUpdate
렌더링 후 동기적으로 실행됩니다.
따라서 를 사용하여requestAnimationFrame
이러한 라이프 사이클에서는, 겉보기에는 별로 효과가 없지만, 약간 문제가 있다.useEffect
따라서 useEffect는 사용자가 변경해야 하는 변경이 응답 수신 후 DOM의 변경을 초래하는 API 호출과 같은 시각적 업데이트를 차단하지 않는 경우에 사용해야 합니다.
가 없지만 할 때 한 또 는 DOM입니다.useLayoutEffect
문서와 같다.
시그니처는 useEffect와 동일하지만 모든 DOM 변환 후 동기적으로 실행됩니다.이를 통해 DOM에서 레이아웃을 읽고 동기적으로 재렌더합니다.「 」내의 되고 .
useLayoutEffect
브라우저가 페인트를 칠하기 전에 동기식으로 플러시됩니다.
따라서 효과가 (DOM 노드 참조를 통해) DOM을 변환하고 DOM 변환에 의해 렌더링된 시점부터 효과가 변환된 시점까지 DOM 노드의 외관이 변경되는 경우 를 사용하지 않습니다.사용하고 싶을 것입니다.useLayoutEffect
않으면 때 깜박임이 수 돌연변이는 DOM의 .것은,, 의의같같다다 다다다다다requestAnimationFrame
//import React, { useState, useEffect } from "react";
const {useState, useLayoutEffect} = React;
//import ReactDOM from "react-dom";
function App() {
const [startSeconds, setStartSeconds] = useState("");
const [progress, setProgress] = useState(0);
useLayoutEffect(() => {
setStartSeconds(Math.random());
const interval = setInterval(() => {
setStartSeconds(Math.random());
}, 1000);
return () => clearInterval(interval);
}, []);
useLayoutEffect(
() => {
let raf = null;
const onFrame = () => {
const currentProgress = startSeconds / 120.0;
setProgress(Math.random());
// console.log(currentProgress);
loopRaf();
if (currentProgress > 100) {
stopRaf();
}
};
const loopRaf = () => {
raf = window.requestAnimationFrame(onFrame);
// console.log('Assigned Raf ID: ', raf);
};
const stopRaf = () => {
console.log("stopped", raf);
window.cancelAnimationFrame(raf);
};
loopRaf();
return () => {
console.log("Cleaned Raf ID: ", raf);
// console.log('init', raf);
// setTimeout(() => console.log("500ms later", raf), 500);
// setTimeout(()=> console.log('5s later', raf), 5000);
stopRaf();
};
},
[startSeconds]
);
let t = [];
for (let i = 0; i < 1000; i++) {
t.push(i);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<text>{progress}</text>
{t.map(e => (
<span>{progress}</span>
))}
</div>
);
}
ReactDOM.render(<App />,
document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0-alpha.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0-alpha.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
언급URL : https://stackoverflow.com/questions/53781632/whats-useeffect-execution-order-and-its-internal-clean-up-logic-when-requestani
'programing' 카테고리의 다른 글
EventSource의 HTTP 인가 헤더(서버가 송신한 이벤트) (0) | 2023.03.06 |
---|---|
리액트 기반 어플리케이션 사용 시 redux와 reflux의 핵심 차이점은 무엇입니까? (0) | 2023.03.06 |
Wordpress: 미디어 라이브러리 그리드 모드 무한 로드 (0) | 2023.03.01 |
반응 - DOM 렌더링 중에 로드 화면을 표시하시겠습니까? (0) | 2023.03.01 |
JSONAray에서 JSONObject 가져오기 (0) | 2023.03.01 |