React의 Lane은 무엇입니까?

13770 단어 Reacttech
React 내부에는 "Lane"이라는 구조가 사용됩니다.
Initial Lanes implementation by acdlite · Pull Request #18796 · facebook/react
며칠 전 리액트 18 알파는 컨투어런트의 기능이 대부분 랜의 기관을 기반으로 제작됐다고 발표했다.
Lane은 32bit로 Reconceile의 작업을 나타냅니다.Lane을 나타내는 실제 코드는 다음과 같습니다.
// https://github.com/facebook/react/blob/9212d994ba939f20a04220a61e9776b488381596/packages/react-reconciler/src/ReactFiberLane.new.js
const NoLane: Lane = 0b0000000000000000000000000000000;
const SyncLane: Lane = 0b0000000000000000000000000000001
const TransitionLanes: Lanes = 0b0000000001111111111111111000000;
const IdleLane: Lanes = 0b0100000000000000000000000000000;
const OffscreenLane: Lane = 0b1000000000000000000000000000000;
위에서 설명한 대로 각 작업 유형에 대해 Lane이 있습니다.NoLane(작업이 없을 때)은 예외지만, 기본적으로 우선도가 높은 Lane일수록 작은 수치로 표시됩니다.
Bitmask는 32비트를 사용하여 Lane 작업에 사용할 수 있습니다.예를 들어 여러 개의 Lane Bitmask를 하나의 Lane에 연결하면 모든 Lane을 상대적으로 비교할 필요가 없고 실현도 간단하며 메모리도 절약할 수 있다.
Bitmask를 실행하는 함수를 실제로 보십시오.
export function mergeLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {
  return a | b;
}
이 함수는 이름과 같이 Lane을 병합하여 반환하는 함수입니다.OR 연산을 사용하여 Lane을 결합합니다.예를 들어 다음과 같이 사용할 수 있다.
mergeLanes(
  NoLane /*0b0000000000000000000000000000000*/,
  OffscreenLane /*0b1000000000000000000000000000000*/
)

// => 0b1000000000000000000000000000000
위의 예에서 작업이 없는 Lane(NoLane)을 OffscreenLane으로 업데이트합니다.Lane은 Fiber와 연결되어 있기 때문에 대상인 Fiber의 Lane을 다음과 같이 업데이트할 수 있습니다.
fiber.lanes = mergeLanes(
  fiber.lanes /* NoLane */, 
  OffscreenLane
)
// => OffscreenLane
또 다른 함수isSubsetOfLanes.
export function isSubsetOfLanes(set: Lanes, subset: Lanes) {
  return (set & subset) === subset;
}
이 함수는 Lane의 AND 계산 결과가 subset과 일치하는지 반환합니다.이것만 쓰면 어떤 기쁨이 있을지 모르니 구체적인 패턴을 몇 개 써 보자.
isSubsetOfLanes(
  NonIdleLanes, /*0b0001111111111111111111111111111*/
  SyncLane /*0b0000000000000000000000000000001*/
)
// => true. SyncLane は Idle なタスクではない

isSubsetOfLanes(
  NonIdleLanes, /*0b0001111111111111111111111111111*/
  OffscreenLane /*0b1000000000000000000000000000000*/
)
// => false. OffscreenLane は Idle なタスク

isSubsetOfLanes(
  TransitionLanes, /*0b0000000001111111111111111000000*/
  TransitionLane1 /*0b0000000000000000000000001000000*/
)
// => true. TransitionLane1 は TransitionLanes に含まれる
위에서 말한 바와 같이 isSubsetOfLanes에서 상응하는 Lane은 대상 Fiber의 서브집합입니까?이렇게 하면 판별할 수 있다.
예를 들어, 함수scheduleWorkOnParentPath가 있습니다.이 함수는 대체적으로 상위의parent에 '하급의children에 임무가 있음' 을 알리는 역할을 한다.
// https://github.com/facebook/react/blob/a8964649bb6332cf1f8d723f81ce97cc5a1886ff/packages/react-reconciler/src/ReactFiberNewContext.new.js#L142
export function scheduleWorkOnParentPath(
  parent: Fiber | null,
  renderLanes: Lanes,
) {
  // Update the child lanes of all the ancestors, including the alternates.
  let node = parent;
  while (node !== null) {
    const alternate = node.alternate;
    if (!isSubsetOfLanes(node.childLanes, renderLanes)) {
      node.childLanes = mergeLanes(node.childLanes, renderLanes);
      if (alternate !== null) {
        alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
      }
    } else if (
      alternate !== null &&
      !isSubsetOfLanes(alternate.childLanes, renderLanes)
    ) {
      alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
    } else {
      // Neither alternate was updated, which means the rest of the
      // ancestor path already has sufficient priority.
      break;
    }
    node = node.return;
  }
}
여기는node.returnparent 또는 여러parent의Fiber이기 때문에parent의 경로 순서에 따라childLanes의 함수를 업데이트하는 것을 알 수 있습니다.예를 들어, children에서 React.Context가 업데이트되었을 때,parent에 이 사실을 전달할 때 사용합니다.
이 함수에 사용합니다isSubsetOfLanes.
    if (!isSubsetOfLanes(node.childLanes, renderLanes)) {
      node.childLanes = mergeLanes(node.childLanes, renderLanes);
      if (alternate !== null) {
        alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes);
      }
    } else if (
node는 여기에서parent를 표시하기 때문에 여기서 "parent.childLanes(코드상node.childLanes)))대상의 Lane 부분 집합이 아니라면parent.childLanes를 대상의 Lane와 합병된 값으로 업데이트합니다."이렇게 하면 children의 Lane을 Parent 옆으로 옮길 수 있습니다.결과적으로, Reconceile 시 fiber.childrenLanes를 보면 하급층이 다시 렌더링해야 한다는 것을 알 수 있습니다.
이렇게 하면 랜 덕분에 여러 임무를 쉽게 취합해 처리할 수 있고, 우선순위가 낮은 경로로 판별할 수 있다.Reconceile 시에는 라인을 참조하고 업데이트·통합하면 돼 본래 알고리즘에 집중할 수 있고, 결과적으로 파이버와 수spense의 생각과 일치하는 아키텍처를 구현할 수 있다.
리액트 18 알파가 구현한 기능 중에는 랜 외에 몇 가지 핵심 PR이 있는데 그 상세한 내용은 다음과 같다.
파이버 제안 이후 지금까지 디자인, 실크, 검증, 디자인을 반복하다 드디어 빅버전이 업그레이드됐는데 대단하지 않나요?나는 신의 발레처럼 감동했다.

좋은 웹페이지 즐겨찾기