성능 향상을 위해 React 이벤트 탐지기를 캐시합니다.
20381 단어 reactreactnativewebdevjavascript
const functionOne = function() { alert('Hello world!'); };
const functionTwo = function() { alert('Hello world!'); };
functionOne === functionTwo; // false
그러나 기존 함수에 변수를 할당하면 차이점을 봅니다.const functionThree = function() { alert('Hello world!'); };
const functionFour = functionThree;
functionThree === functionFour; // true
객체의 작업 방식이 동일합니다.const object1 = {};
const object2 = {};
const object3 = object1;
object1 === object2; // false
object1 === object3; // true
만약 네가 다른 언어의 경험이 있다면, 너는 지침에 익숙해질 것이다.여기서 발생하는 일은 대상을 만들 때마다 장치에 메모리를 분배하는 것이다.내가 object1 = {}
이라고 말했을 때, 나는 사용자의 RAM에 object1
을 위한 바이트를 만들었다.object1
을 RAM에 대한 키 값을 포함하는 주소로 상상할 수 있습니다.object2 = {}
이라고 말할 때, 나는 사용자의 RAM에 object2
에 전문적으로 사용되는 다른 바이트 블록을 만들었다.object1
의 주소와 object2
의 주소가 일치합니까?아니오. 이것이 바로 이 두 변수의 등식 검사가 통과되지 않은 이유입니다.그것들의 키 값은 완전히 같을 수 있지만, 메모리에 있는 주소는 다르다. 이것이 바로 비교할 부분이다.내가
object3 = object1
의 값을 부여했을 때, 나는 object3
의 값을 object1
의 주소로 부여했다.그것은 새로운 대상이 아니다.그것은 메모리의 같은 위치이다.다음과 같이 확인할 수 있습니다.const object1 = { x: true };
const object3 = object1;
object3.x = false;
object1.x; // false
이 예에서, 나는 메모리에 대상을 만들고 object1
에 분배했다.그리고 나는 object3
을 메모리의 같은 주소에 분배할 것이다.변이 object3
을 통해 나는 메모리에서 이 위치의 값을 바꾸었다. 이것은 메모리에서 이 위치에 대한 모든 다른 인용도 바뀐다는 것을 의미한다.object1
은 메모리의 위치를 가리키며 변경된 값이 있습니다.초급 개발자에게 이것은 매우 흔히 볼 수 있는 잘못으로 자신의 깊이 있는 강좌가 필요할 가능성이 높다.그러나 본 강좌는 React 성능에 관한 것으로 경력이 높은 개발자라도 성능에 영향을 미칠 수 있다. 왜냐하면 그들은 변수 인용의 의미를 전혀 고려하지 않기 때문이다.
이것은 React와 어떤 관계가 있습니까?React는 처리 시간을 절약하여 성능을 향상시키는 스마트 방법이 있습니다. 만약에 Pure Component의 도구와 상태가 변하지 않는다면
render
의 출력도 변하지 않을 것입니다.분명히 모든 것이 평등하다면, 모든 것은 변하지 않을 것이다.만약 아무런 변경이 없다면, render
은 반드시 같은 출력을 되돌려야 하기 때문에, 우리는 그것을 실행할 필요가 없다.이것이 바로 왜 반응이 신속한가 하는 것이다.필요할 때만 렌더링됩니다.React에서 도구와 상태가 JavaScript와 동일한지 확인 —
==
연산자와 비교하기만 하면 됩니다.React는 객체가 동일한지 여부를 결정하기 위해 얕거나 깊게 비교되지 않습니다.얕은 층 비교는 비교 대상의 키 값 쌍을 설명하는 용어로 메모리 주소를 비교하는 것이 아니다.깊이가 더욱 깊어진다. 만약에 키 값이 중의 어떤 값도 대상이라면 이런 키 값이 맞다는 것도 이상한 느낌이다.React는 둘 다 하지 않습니다. 인용이 같은지 확인하는 것뿐입니다.구성 요소의 도구를
{ x: 1 }
에서 다른 대상 { x: 1 }
으로 변경하려면 메모리에서 참조하는 위치가 다르기 때문에 React가 다시 렌더링됩니다.구성 요소의 도구를 object1
(위쪽)에서 object3
으로 변경하려면 두 대상이 같은 참조이기 때문에 React는 다시 렌더링되지 않습니다.함수는 JavaScript에서 동일하게 처리됩니다.React가 다른 메모리 주소가 있는 동일한 함수를 수신하면 다시 렌더링됩니다.React가 같은 함수 참조를 수신하는 경우에는 그렇지 않습니다.
불행하게도 이것은 내가 코드 심사 기간에 만난 흔한 장면이다.
class SomeComponent extends React.PureComponent {
get instructions() {
if (this.props.do) {
return 'Click the button: ';
}
return 'Do NOT click the button: ';
}
render() {
return (
<div>
{this.instructions}
<Button onClick={() => alert('!')} />
</div>
);
}
}
이것은 매우 간단한 구성 요소다.버튼을 누르면 경보가 울린다.do={true}
의 do={false}
또는 SomeComponent
아이템으로 제어할 수 있습니다.여기서 발생하는 일은 매번
SomeComponent
을 다시 렌더링하는 것이다(예를 들어 do
에서 true
으로 전환), false
도 다시 렌더링하는 것이다!Button
프로세서는 완전히 같지만 onClick
호출할 때마다 생성됩니다.렌더링할 때마다 메모리에 새 함수 (렌더링 함수에서 생성된 것이기 때문에) 를 만들고 메모리에 있는 새 주소에 대한 새 인용을 render
에 전달하며 <Button />
구성 요소를 다시 렌더링합니다. 출력에 변경된 것이 전혀 없지만.고치다
함수가 구성 요소에 의존하지 않으면 (
Button
상하문이 없음) 구성 요소 외부에서 정의할 수 있습니다.구성 요소의 모든 실례는 함수가 모든 상황에서 같기 때문에 같은 함수를 사용합니다.const createAlertBox = () => alert('!');
class SomeComponent extends React.PureComponent {
get instructions() {
if (this.props.do) {
return 'Click the button: ';
}
return 'Do NOT click the button: ';
}
render() {
return (
<div>
{this.instructions}
<Button onClick={createAlertBox} />
</div>
);
}
}
이전 예와 달리 this
은 createAlertBox
동안 메모리의 동일한 위치에 대한 동일한 참조를 유지합니다.따라서 render
을 다시 렌더링할 필요가 없습니다.Button
은 작고 빠르게 렌더링되는 구성 요소일 수 있지만, 대형, 복잡하고 렌더링 속도가 느린 구성 요소에서 이러한 내연 정의를 볼 수 있으며, React 응용 프로그램을 곤경에 빠뜨릴 수 있습니다.렌더링 방법에서 이 함수를 정의하지 않는 것이 좋습니다.함수가 구성 요소에 의존하므로 구성 요소 외부에서 정의할 수 없는 경우 구성 요소의 방법을 이벤트 프로세서로 전달할 수 있습니다.
class SomeComponent extends React.PureComponent {
createAlertBox = () => {
alert(this.props.message);
};
get instructions() {
if (this.props.do) {
return 'Click the button: ';
}
return 'Do NOT click the button: ';
}
render() {
return (
<div>
{this.instructions}
<Button onClick={this.createAlertBox} />
</div>
);
}
}
이런 상황에서 Button
의 실례마다 다른 경보 상자가 있다.SomeComponent
의 클릭 사건 감청기는 Button
의 유일한 감청기가 필요하다.SomeComponent
을 전달하는 방법을 통해 createAlertBox
의 재렌더링 여부는 중요하지 않습니다.SomeComponent
아이템 변경 여부는 중요하지 않습니다!message
메모리의 주소는 변하지 않습니다. 이것은 createAlertBox
을 다시 렌더링할 필요가 없고 처리 시간을 절약하고 응용 프로그램의 렌더링 속도를 높일 수 있음을 의미합니다.그런데 만약에 제 함수가 동적이라면요?
수정 (고급)
저자 주: 나는 기억에서 같은 기능을 반복적으로 인용하는 방법으로 아래의 예를 썼다.이런 예들은 참고 문헌의 이해를 쉽게 하는 데 목적을 두고 있다.참고 문헌을 이해하기 위해 이 절을 읽을 것을 건의하지만 마지막으로 더 좋은 실현을 소개했습니다. 이것은 Chris Ryan이 평론을 통해 아낌없이 제공한 것입니다.그의 해결 방안은 캐시 실효와 React의 내장 메모리 관리를 고려했다.
하나의 구성 요소에 많은 독특한 동적 이벤트 탐지기가 있는데, 예를 들어 맵 그룹을 만들 때.
class SomeComponent extends React.PureComponent {
render() {
return (
<ul>
{this.props.list.map(listItem =>
<li key={listItem.text}>
<Button onClick={() => alert(listItem.text)} />
</li>
)}
</ul>
);
}
}
이 경우 이벤트 감청기의 수를 변경할 수 있는 수량 변경 단추가 있습니다. 모든 감청기는 독특한 기능을 가지고 있습니다. Button
을 만들 때 무엇인지 알 수 없습니다.너는 어떻게 이 난제를 해결할 수 있니?memoization을 입력하거나caching이라고 부르기 쉬운 내용을 입력하십시오.모든 유일한 값에 대해 함수를 만들고 캐시합니다.나중에 이 유일한 값에 대한 모든 인용은 이전에 캐시된 함수로 되돌려주십시오.
이것이 바로 내가 어떻게 상술한 예시를 실현할 것인가이다.
class SomeComponent extends React.PureComponent {
// Each instance of SomeComponent has a cache of click handlers
// that are unique to it.
clickHandlers = {};
// Generate and/or return a click handler,
// given a unique identifier.
getClickHandler(key) {
// If no click handler exists for this unique identifier, create one.
if (!Object.prototype.hasOwnProperty.call(this.clickHandlers, key)) {
this.clickHandlers[key] = () => alert(key);
}
return this.clickHandlers[key];
}
render() {
return (
<ul>
{this.props.list.map(listItem =>
<li key={listItem.text}>
<Button onClick={this.getClickHandler(listItem.text)} />
</li>
)}
</ul>
);
}
}
수조의 모든 항목은 SomeComponent
방법을 통해 전달된다.처음 값을 사용하여 이 방법을 호출할 때, 이 방법은 이 값의 유일한 함수를 만들고 이 함수를 되돌려줍니다.앞으로 이 값을 사용하여 이 방법에 대한 호출은 새 함수를 만들지 않습니다.반대로 메모리에 생성된 함수에 대한 인용을 되돌려줍니다.따라서
getClickHandler
을 다시 렌더링하면 SomeComponent
이 다시 렌더링되지 않습니다.이와 유사하게 Button
아이템에 항목을 추가하면 버튼마다 이벤트 탐지기를 동적으로 만들 수 있습니다.각 프로세서가 여러 변수에 의해 결정될 때, 당신은 자신의 총명한 재능을 사용하여 유일한 식별자를 생성해야 할 수도 있지만, 이것은 단순히 매핑 결과의 모든 JSX 대상에 유일한
list
도구를 생성하는 것보다 그리 어렵지 않습니다.key
을 식별자로 사용하는 경고: 목록이 순서를 변경하거나 항목을 삭제하면 잘못된 결과를 얻을 수 있습니다.그룹 수가 index
에서 [ 'soda', 'pizza' ]
으로 변경되고 이벤트 탐지기를 [ 'pizza' ]
으로 캐시하면 사용자가 피자의now-index-0 단추를 눌렀을 때 listeners[0] = () => alert('soda')
에 경보를 보냅니다.이것은 React가 관건적인 도구에 그룹 인덱스를 사용하지 말라고 건의한 이유와 같습니다.더 나은 구현
중간 사용자인 Chris Ryan이 제공합니다.
결론
만약 당신이 이 문장을 좋아한다면, 마음대로 그것에게 마음이나 딱정벌레를 주십시오.그것은 매우 빠르고, 매우 쉬우며, 게다가 무료이다.질문이나 조언이 있으면 아래 댓글로 남겨주세요.
제 칼럼을 더 많이 읽으려면 Medium과, 또는 check out my portfolio on CharlesStover.com을 따르세요.
Reference
이 문제에 관하여(성능 향상을 위해 React 이벤트 탐지기를 캐시합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/charlesstover/cache-your-react-event-listeners-to-improve-performance-3i76텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)