본문 바로가기
TIL

React - Rerendering 조건 (22.11.10 TIL)

by winteringg 2022. 11. 10.

리액트에서 상태 변수는 브라우저에서 구성 요소 상태를 렌더링하는 데 사용된다. 상태가 변경되면 리액트는 새 데이터로 구성 요소를 다시 렌더링한다. 프로그램에서 발생하는 모든 변경 사항을 사용자에게 (상태가 변경될 시) 바로 알려준다.

Rerendering 조건

1. state (상태) 변경이 있을 때
- state 변경이 감지되면 리렌더링 한다.

2. 새로운 props 가 들어왔을 때
- 부모 컴포넌트로부터 새 props 가 들어오면 자식 컴포넌트는 리렌더링 된다.

3. 기존 props 가 업데이트 됐을 때
- 부모 컴포넌트로부터 받은 props 가 변경되면 props 값을 받은 자식 컴포넌트도 리렌더링 된다.

4. 부모 컴포넌트가 리렌더링 될 때
- 부모 컴포넌트가 업데이트 되어 리렌더링 되면 자식 컴포넌트도 리렌더링 된다.

비교 알고리즘 - Object.is()

Object.is() 알고리즘은 다음과 같은 경우 두 값이 동일한 지 여부를 결정한다.

  • 두 값 모두 undefined 또는 null 일 경우
  • 두 값 모두 true 또는 false 일 경우
  • 두 값 Strings 의 문자, 길이 및 순서가 동일한 경우
  • 두 값 모두 동일한 값의 Numbers 이거나 NaN 인 경우
  • 두 값 모두 동일한 메모리 위치를 가리키고 있는 Objects 인 경우
const [이름, setName] = useState('');

const onButtonClick = (newName: string)=> { 
   setName(newName); 
};

위 코드에서 리액트는 새 값이 변수에 할당 될 때마다 Object.is() 비교 알고리즘을 사용하여 name 변수에 새 값이 할당 될 경우 이전 값과 동일한 지 비교한다. 값이 같을 경우 렌더링을 진행하지 않고, 값이 다르면 상태 변경을 반영하기 위해 구성 요소를 다시 렌더링한다.

참조 평등

const App = () => {
  const [mySelf, setMySelf] = useState<{ name: string, age: number }>({ name: 'David', age: 30 });

      const changeNameToJohn = () => {
        mySelf.name = "John";
        mySelf.age = 30;
        console.log(mySelf);
        setMySelf(mySelf)
      }
  }

위 코드에서는 mySelf 속성이 있는 객체에 초기화되고 각각 name 과 age 에 'David' 및 '30' 으로 설정된 상태 변수가 들어간다. 또한 'John' 이라는 새 값을 name 에 다시 넣어주기 위해 이벤트 리스너 changeNameToJohn 을 선언했다. 

만약 이 함수가 호출되면 name 은 'John' 으로 변경되고 UI 를 업데이트 하기 위해 리렌더링 되어야 한다. 하지만 실제로 객체를 로딩하면 업데이트 된 값이 콘솔에는 표시되지만 실제 UI 는 바뀌지 않는다. 그 이유는 Object.is() 알고리즘의 다섯 번째 원칙을 보면 알 수 있다.

두 객체가 정확한 메모리 위치를 가리킬 때 두 값은 동일한 것으로 간주된다


위 코드에 표시 된 상태 변경 중에 현재 개체의 속성에 새 이름을 할당하지만, 리액트에서 비교 알고리즘을 적용하면 두 값이 동일한 메모리 위치를 가리키기 때문에 새 값과 현재 값은 여전히 동일하다. 따라서 리액트는 이러한 값을 동일한 것으로 분류하고 리렌더링하지 않는다. 따라서, UI 는 상태 변경을 반영하지 않는다.

이러한 프로스세를 참조 동등성 이라고 한다. 객체는 값이 아니라 메모리 위치에 따라 동일한 것으로 간주된다. 이 사실을 고려하면 UI 에 반영되도록 리렌더링 시키는 방법은 간단하다.

const changeNameToJohn = () => { 
   setMySelf({ ...mySelf, name: '존' }); 
}


...mySelf 를 통해 새로운 객체를 만들어서 name 에 값을 할당하면, 기존 객체를 업데이트하는 대신 새 객체가 메서드에 전달된다. 따라서 리액트가 알고리즘을 적용할 때 전달되는 값은 새 객체가 다른 메모리 위치를 가리키기 때문에 mySelf 는 결과적으로 상태가 업데이트되어 리렌더링을 할 수 있게 된다.


참고 :

 

Understanding Referential Equality in React

What is referential equality? Why it is useful to understand, and how referential equality affects component re-rendering in React

blog.bitsrc.io

 

댓글