리액트에서 상태 변수는 브라우저에서 구성 요소 상태를 렌더링하는 데 사용된다. 상태가 변경되면 리액트는 새 데이터로 구성 요소를 다시 렌더링한다. 프로그램에서 발생하는 모든 변경 사항을 사용자에게 (상태가 변경될 시) 바로 알려준다.
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 는 결과적으로 상태가 업데이트되어 리렌더링을 할 수 있게 된다.
참고 :
'TIL' 카테고리의 다른 글
자바스크립트 동기와 비동기 (22.11.12 TIL) (0) | 2022.11.12 |
---|---|
나만의 메뉴 구현 (22.11.11 TIL) (0) | 2022.11.11 |
React - require vs import (22.11.09 TIL) (0) | 2022.11.09 |
controller 간단하게 만들기 (22.11.08 TIL) (0) | 2022.11.08 |
Java - 내부 클래스(중첩 클래스), 익명 클래스 (22.11.07 TIL) (0) | 2022.11.07 |
댓글