본문 바로가기

공부기록/React

컴포넌트의 리렌더링 조건

리액트의 렌더링 시기

https://velog.io/@eunbinn/when-does-react-render-your-component#%ED%9D%90%EB%A6%84%EB%8F%84

 

렌더링의 유형

1. 능동적인 렌더링 

    컴포넌트가 능동적으로 상태변경 업데이트 예약 

    ReactDOM.render호출

2. 수동적인 렌더링

    부모 컴포넌트가 상태 업데이트 예약 했는데, 

    컴포넌트가 렌더링 제외 기준을 충족하지 못함

 

 

1. 능동적인 렌더링 

  • 클래스 컴포넌트 : Component.prototype.setState
  • 함수형 컴포넌트 : 훅에 의해 발생한 dispatchAction (useReducer훅, useState 훅등)
  • ReactDOM.render 호출

 

2. 수동적인 렌더링

 

수동적 렌더링 제외기준

  • 이미 마운트 됨 
  • 변경된 props가 없음
  • 컴포넌트에서 사용되는 context값 중 변경된 것이 없음 
  • 컴포넌트 자체에서 업데이트 예약하지 않음

부모가 렌더링 될 때 자식은 렌더링된다 (제외기준 충족하지 않았을 경우)

 

 

 

 

렌더링 제외하는 방법 

* 직접 부모 컴포넌트 내부에 넣지 않고 children으로 감싸거나 props로 넘겨줬을때 제외

default function App() {
  return (
    <Parent lastChild={<ChildC />}>
      <ChildB />
    </Parent>
  );
}

function Parent({ children, lastChild }) {
  return (
    <div className="parent">
      <ChildA /> //리렌더링 된다 
      {children}
      {lastChild}
    </div>
  );
}

function ChildA() {
  return <div className="childA"></div>;
}

function ChildB() {
  return <div className="childB"></div>;
}

function ChildC() {
  return <div className="childC"></div>;
}

 

1. props 변경하지 않는 방법 

props는 컴포넌트의 React.createElement에서 생성한 ReactElement의 속성 

ReactElement는 불변이므로 

리액트가 컴포넌트를 렌더링 할 때마다 React.createElement에서 ReactElement를 생성

(리렌더링 할 때마다 생성)

 

function Parent() {
  return (
    <div>
      <Child />
    </div>
  );
}

 

<Child />는 Babel에 의해

React.createElement(Child, null)로 컴파일

{type: Child, props: {}}  형태의 ReactElement가 생성

 

2. 리액트가 props변경을 탐지하는 데 사용하는 규칙을 변경

 

React.memo로 감쌀 경우 props변경을 확인할 다른 방법 제공

(이런경우 props의 모든 property에 아래와 비슷한 얕은 비교를 수행)

Object.keys(prevProps).some(key => prevProps[key] !== nextProps[key])

 

그러나 이것은 악용되면 안됨

props 비교에 드는 비용을 무시하면 안됨 

 

3. context값을 변경하지 않는 방법 

 

 비-원시 context값을 useMemo로 래핑하여 참조적으로 동일하게 유지

 

 

function Parent({ children, lastChild }) {
  const contextValue = {};
  const memoizedCxtValue = useMemo(contextValue);
  return (
    <div className="parent">
      <Context.Provider value={memoizedCxtValue}>
        <ChildA />
        {children}
        {lastChild}
      </Context.Provider>
    </div>
  );
}

예외 

context provider 컴포넌트가 컴포넌트 트리의 최상단에 있으면 context값을 기억할 필요 없음.

 

 

암묵적인 전제

 

  • 동일한 위치에서 다른 컴포넌트 간에 전환
  • 같은 컴포넌트를 다른 위치에 렌더링
  • 의도적으로 key를 변경