야생의 연결 목록: React Hooks
감사합니다. 다음: 연결 목록 소개
Ali Spittel ・ 12월 5일 ・ 5분 읽기
#datastructures
#beginners
#programming
#javascript
다이빙을 하던 중 후크가 실제로 후드 아래에서 연결된 목록을 사용하고 있음을 알았습니다. 데이터 구조의 구현 또는 사용 사례에서 실행하는 것은 항상 멋진 일이므로 내가 알 수 있는 한 사용 방법과 이유를 공유해야 한다고 생각했습니다.
구현
후크 구현에는 다음과 같은 주석이 있습니다.
// Hooks are stored as a linked list on the fiber's memoizedState field. The
// current hook list is the list that belongs to the current fiber. The
// work-in-progress hook list is a new list that will be added to the
// work-in-progress fiber.
섬유가 무엇인지 모르더라도 걱정하지 마십시오. 기본적으로 React에서 작업 단위의 코드 표현입니다. 원본Fiber github에서:
- pause work and come back to it later.
- assign priority to different types of work.
- reuse previously completed work.
- abort work if it's no longer needed.
따라서 후크는 파이버의 상태로 저장됩니다. 파이버에는 현재 후크의 연결된 목록이 있습니다. React에서 무언가가 업데이트되면 파이버는 새로운 진행 중인 후크 목록을 생성하고 목록에 추가합니다.
다음은 the React src의 후크 구현입니다(주석은 코드 자체에서 가져옴).
function createWorkInProgressHook(): Hook {
if (workInProgressHook === null) {
// This is the first hook in the list
if (firstWorkInProgressHook === null) {
isReRender = false;
currentHook = firstCurrentHook;
if (currentHook === null) {
// This is a newly mounted hook
workInProgressHook = createHook();
} else {
// Clone the current hook.
workInProgressHook = cloneHook(currentHook);
}
firstWorkInProgressHook = workInProgressHook;
} else {
// There's already a work-in-progress. Reuse it.
isReRender = true;
currentHook = firstCurrentHook;
workInProgressHook = firstWorkInProgressHook;
}
} else {
if (workInProgressHook.next === null) {
isReRender = false;
let hook;
if (currentHook === null) {
// This is a newly mounted hook
hook = createHook();
} else {
currentHook = currentHook.next;
if (currentHook === null) {
// This is a newly mounted hook
hook = createHook();
} else {
// Clone the current hook.
hook = cloneHook(currentHook);
}
}
// Append to the end of the list
workInProgressHook = workInProgressHook.next = hook;
} else {
// There's already a work-in-progress. Reuse it.
isReRender = true;
workInProgressHook = workInProgressHook.next;
currentHook = currentHook !== null ? currentHook.next : null;
}
}
return workInProgressHook;
}
이에 대해 조금 더 살펴보겠습니다.
if (workInProgressHook === null) {
사용 중인 현재 후크가 있는지 확인 중입니다.
workInProgressHook
전역 변수이며 다음과 같이 사용됩니다.workInProgressHook = createWorkInProgressHook();
따라서
workInProgressHook
가 null이면 어떻게 해야 할까요?null workInProgressHook은 현재 후크를 빌드하고 있지 않음을 의미합니다. 즉, 목록에서 다음 후크를 빌드하지 않고 현재 후크로 작업하려고 합니다. 새 목록을 만들고 첫 번째 요소를 만들 때와 다시 렌더링할 때, 기존 목록을 다시 로드할 때 이렇게 두 번 할 수 있습니다. 다음
if
문장은 우리에게 이것을 보여줍니다.// This is the first hook in the list
if (firstWorkInProgressHook === null) {
isReRender = false;
currentHook = firstCurrentHook;
if (currentHook === null) {
// This is a newly mounted hook
workInProgressHook = createHook();
} else {
// Clone the current hook.
workInProgressHook = cloneHook(currentHook);
}
firstWorkInProgressHook = workInProgressHook;
} else {
// There's already a work-in-progress. Reuse it.
isReRender = true;
currentHook = firstCurrentHook;
workInProgressHook = firstWorkInProgressHook;
}
firstWorkInProgressHook
가 없으면 연결 목록 작성을 시작해야 합니다. 여기에는 또 다른 if 문이 있습니다. 그러나 만약 우리가 가지고 있다면 그것은 우리가 이미 진행 중인 작업을 만들고 있고 첫 번째 현재 후크를 복사할 수 있다는 것을 의미합니다!다음 if 문은 다음과 같습니다.
if (currentHook === null) {
// This is a newly mounted hook
workInProgressHook = createHook();
} else {
// Clone the current hook.
workInProgressHook = cloneHook(currentHook);
}
이제 현재 후크가 있는지 확인하려고 합니다. 그렇지 않으면 완전히 새로운 목록을 만드는 것이므로
createHook
를 호출합니다.
createHook
just returns a object with a bunch of null set properties. The one we will be interested in thenext
property.
그렇지 않으면 이미 한 번 렌더링한 목록입니다. React는 이 함수가 호출될 때마다 후크를 다시 생성할 필요가 없도록 훅을 복제하고 계속 진행함으로써 일부 성능을 절약합니다.
이제 첫 번째 후크가 있습니다!
firstWorkInProgressHook
를 방금 만든 새 항목으로 설정했습니다!firstWorkInProgressHook = workInProgressHook;
이제
createWorkInProgressHook
를 다시 호출하면 어떻게 됩니까?function createWorkInProgressHook(): Hook {
if (workInProgressHook === null) {
// ...
} else {
// what happens here?
}
return workInProgressHook;
}
한번 보자!
이제
workInProgressHook
가 null이 아니므로 다음 후크가 있는지 확인해야 합니다.if (workInProgressHook.next === null) {
없는 경우 새 후크를 만들어 목록에 추가해야 합니다. 정확히 다음과 같습니다.
isReRender = false;
let hook;
if (currentHook === null) {
// This is a newly mounted hook
hook = createHook();
} else {
currentHook = currentHook.next;
if (currentHook === null) {
// This is a newly mounted hook
hook = createHook();
} else {
// Clone the current hook.
hook = cloneHook(currentHook);
}
}
// Append to the end of the list
workInProgressHook = workInProgressHook.next = hook;
따라서 복제할 현재 후크가 있는지 다시 확인합니다(이번에는 다음 후크가 존재하는지 확인합니다. 이 후크가 이전에 생성되었는지 알 수 있기 때문입니다). 있는 경우 복제하고 없으면 새로 만듭니다.
그런 다음 이 매직 라인을 호출합니다.
workInProgressHook = workInProgressHook.next = hook;
새로 생성된 후크를 가져와 현재 후크의 다음 후크로 설정한 다음 현재 후크를 새 후크와 동일하게 설정합니다. 이것은 기본적으로 다음과 동일합니다.
workInProgressHook.next = hook;
workInProgressHook = hook;
마지막으로 작업 중인 후크가 이미 있는 경우 다시 렌더링하고 처음에 했던 것과 거의 동일한 작업을 수행하려고 합니다.
} else {
// There's already a work-in-progress. Reuse it.
isReRender = true;
workInProgressHook = workInProgressHook.next;
currentHook = currentHook !== null ? currentHook.next : null;
}
여기서 유일한 차이점은 하나를 이동하기 전에 currentHook을 다음 후크로 업데이트해야 한다는 것입니다. 이 작업은 마지막 줄에서 해당 삼항으로 수행됩니다.
일부 전역 변수와 함수를 사용하여 연결 목록을 만들었습니다! 꽤 괜찮은데!
솔직히 실제 코드에서 사용되는 연결 목록을 본 것은 이번이 처음일 것입니다! 바라건대, 이 게시물이 의미가 있습니다! 질문이 있으면 알려주세요!
Reference
이 문제에 관하여(야생의 연결 목록: React Hooks), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/wuz/linked-lists-in-the-wild-react-hooks-3ep8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)