React의 Idle-Until-Urgent 패턴
볼 수도 있습니다.
한 가지 가능한 해결 방법은 Idle-Until-Urgent 패턴을 사용하는 것입니다. Philip Walton은 his blog post on the matter에서 패턴의 세부 사항을 설명할 수 있는 것보다 훨씬 더 잘 수행하므로 확인하는 것이 좋지만 패턴의 기본 요점은 다음과 같습니다.
React 사용 사례에서 이것이 의미하는 바는 브라우저가 코드 실행을 중지하거나 사용자가 수화되지 않은 요소와 상호 작용하는 경우 필요에 따라 수화할 수 있을 때까지 구성 요소의 수화를 지연한다는 것입니다. 내 구현은 처음에 .
코드
이것은 긴급할 때까지 유휴 패턴을 사용하도록 다른 React 구성 요소를 감싸는 구성 요소입니다.
import React, { useState, ReactNode, useEffect } from 'react';
// This is a simple library we use to tell us if the code is running in Node or in a browser.
import isNode from 'detect-node';
export const IdleUntilUrgent = ({ children, htmlElement }) => {
const [callbackId, setCallbackId] = useState(null);
const [renderChild, setRenderChild] = useState(false);
useEffect(() => {
if (!isNode) {
if (typeof window.requestIdleCallback !== 'undefined') {
// https://caniuse.com/#search=requestIdleCallback
setCallbackId(
window.requestIdleCallback(() => {
setRenderChild(true);
}),
);
} else {
setTimeout(() => {
setRenderChild(true);
});
}
}
}, []);
if (!isNode && !renderChild) {
// eslint-disable-next-line react/no-danger-with-children
return React.createElement(
htmlElement,
{
dangerouslySetInnerHTML: { __html: '' },
suppressHydrationWarning: true,
onClick: () => setRenderChild(true),
},
null,
);
}
// Cancel the already scheduled render, if any
if (!isNode && callbackId) {
window.cancelIdleCallback(callbackId);
}
return children;
};
사용 시 다음과 같이 표시됩니다.
<IdleUntilUrgent htmlElement="button">
<button>Click me</button>
</IdleUntilUrgent>
그것을 분해
먼저 필요한 두 비트의 상태를 저장합니다. 콜백 ID(필요한 경우 콜백을 취소할 수 있도록) 및 자식을 렌더링해야 하는지 여부를 알려주는 플래그입니다.
const [callbackId, setCallbackId] = useState(null);
const [renderChild, setRenderChild] = useState(false);
다음으로
useEffect
API를 사용하여 콜백을 설정하는 한 번만 트리거되는 requestIdleCallback
후크를 사용합니다. 브라우저가 유휴 상태일 때마다 트리거됩니다. 모든 브라우저에서 지원되지 않으므로 다음 이벤트 루프에서 트리거되는 시간 제한을 사용하는 백업 옵션이 있습니다.useEffect(() => {
if (!isNode) {
if (typeof window.requestIdleCallback !== 'undefined') {
// https://caniuse.com/#search=requestIdleCallback
setCallbackId(
window.requestIdleCallback(() => {
setRenderChild(true);
}),
);
} else {
setTimeout(() => {
setRenderChild(true);
});
}
}
}, []);
브라우저에서 렌더링 중이고 여전히 유휴 또는 긴급 콜백을 기다리고 있는 경우 수화를 건너뛰고 싶습니다. 이것은
dangerouslySetInnerHTML={{ __html: '' }}
로 반응 요소를 반환함으로써 가능합니다. 한 가지 주의할 점은 onClick: () => setRenderChild(true)
입니다. 이것은 패턴의 "긴급"부분입니다. 사용자가 요소를 클릭하면 구성 요소를 즉시 수화시키려는 것입니다. 주목해야 할 또 다른 중요한 점은 동일한 유형의 HTML 요소를 렌더링하는 경우에만 작동한다는 것입니다. 처음에 <div dangerouslySetInnerHTML={{ __html: '' }}><button>click me</button></div>
와 같은 것을 작성하면서 함정에 빠졌습니다.if (!isNode && !renderChild) {
// eslint-disable-next-line react/no-danger-with-children
return React.createElement(
htmlElement,
{
dangerouslySetInnerHTML: { __html: '' },
suppressHydrationWarning: true,
onClick: () => setRenderChild(true),
},
null,
);
}
마지막 부분은 매우 간단합니다. 노드에 있고 정상적으로 렌더링하고 싶거나
renderChild
가 참이면 유휴 콜백이 트리거되었거나 사용자가 요소를 클릭했기 때문에 수화할 시간입니다(콜백 정리). .if (!isNode && callbackId) {
window.cancelIdleCallback(callbackId);
}
return children;
성능 영향
우리는 fishbrain.com에서 가장 많이 방문한 페이지 중 하나인 waters 페이지(here's an example of one such page)에서 이것을 테스트하기로 했습니다. React 렌더의 화염 그래프는 다음과 같습니다.
일부 구성 요소는 너무 깊이 실행되어 화면에 맞지 않습니다. 특히 나쁜 범죄자는 Tabs 구성 요소였습니다.
여기에서 우리는 사용자 혜택을 위해 즉시 렌더링해야 하는 항목이 아니지만 수화하는 데 오랜 시간이 걸리는 4개의 특정 구성 요소를 식별할 수 있습니다. 이러한 구성 요소를 감싸면 수화 시간이 약 450ms에서 <100ms로 감소했습니다!
또한 IdleUntilUrgent 구성 요소가 초기 수화 후 매우 빠르게 수화되므로(보통 0.5초 미만) 매우 빠른 사용자만 유휴 구성 요소와 상호 작용할 수 있습니다.
결론
위에서 말한 모든 것은 우리가 이것을 모든 곳에서 사용할 패턴이 아닙니다. 이러한 종류의 성능 해킹에서 일반적으로 그렇듯이 특정 경우에만 사용하고 싶은 것이지만 이러한 경우에는 매우 유용한 도구입니다.
http://lukehansford.me/posts/the-idle-until-urgent-pattern-in-react에서 원래 게시됨
Reference
이 문제에 관하여(React의 Idle-Until-Urgent 패턴), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/lhansford/the-idle-until-urgent-pattern-in-react-3473텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)