개발의변화
모던리액트딥다이브 - 01 동등비교 본문
자바스크립트 동등비교
리액트로 코드를 짜다보면 렌더링의 문제가 골치 아픈데 특히 props의 변화를 체크하는 일이 쉽지 않았다.
props의 동등비교는 객체의 얕은 비교(Shallow Copy)를 기반으로 이뤄지는데, 이 얕은 비교를 리액트가 어떻게 이해하는 지를 알아야 렌더링 문제를 잡을 수 있다.
1.1 자바스크립트 데이터 타입
자바스크립트는 총 7개의 원시타입과 1개의 객체타입을 가지고 있다.
underfined : 변수를 선언한 후 값을 할당하지 않은 변수에 자동으로 할당되는 값
let foo;
typeof foo === undefined; // true
function bar(hello) {
return hello;
}
typeof bar() === 'undefined' // true
null: 아직 값이 없거나 비어 있는 값을 표현할 때 사용
type null === 'object'
null을 object로 반환이 된다는 점이다.
즉 null은 명시적으로 비어있음을 나타내는 것이고 undefined는 선언됐지만 할당되지 않는 값으로 판단하면 된다.
boolean :
false = 0,false, -0, 0n, 0x0n, '',"",null,undefined
true = 그 외 나머지
number: -2의 53제곱 + 1 ~ 2의 53제곱 - 1
bigint: 2의 53제곱 - 1 이상의 값을 나타낼 때
string :
문자열이 원시타입이며 변경 불가능하다.
문자열이 생성되면 그 문자열을 변경할 수 없음을 의미
const foo = 'bar'
foo[0] = f;
console.log(foo) // bar
symbol:
중복되지 않는 어떠한 고유한 값을 나타내기 위해만들어졌다.
object
객체는 참조값으로 이루어져 있기에 동등비교시 주의해야 한다.
Object.is(인수1,인수2)
- == vs Object.is: == 비교는 같음을 비교하기 전에 양쪽이 같은 타입이 아니라면 비교할 수 있도록 강제로 형변환 한 후에 변경
따라서 5 == '5'와 같이 형변환 후에 값이 동일하다면 ==는 true를 반환, Object.is는 이러한 작업 x
-0 === +0 // true
Object.is(-0,+0) // false
Number.NaN === Nan //false
Object.is(Number.NaN, NaN) // true
그렇다면 리액트에서는 어떻게 비교를 하고 있을까
shallowequal 함수를 활용한 동등비교를 지원하고 있다.
import is from './objectIs';
import hasOwnProperty from './hasOwnProperty';
/**
* Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments.
* Returns true when the values of all keys are strictly equal.
*/
function shallowEqual(objA: mixed, objB: mixed): boolean {
if (is(objA, objB)) {
return true;
}
if (
typeof objA !== 'object' ||
objA === null ||
typeof objB !== 'object' ||
objB === null
) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
for (let i = 0; i < keysA.length; i++) {
const currentKey = keysA[i];
if (
!hasOwnProperty.call(objB, currentKey) ||
// $FlowFixMe[incompatible-use] lost refinement of `objB`
!is(objA[currentKey], objB[currentKey])
) {
return false;
}
}
return true;
}
export default shallowEqual;
리액트 팀에서 구현한 shallowEqual은 객체의 1depth까지는 비교 가능
shallowEqual({hello:'world'}, {hello: 'world' })
얕은 비교까지만 구현한 이유는 props만 일차적으로 비교하면 되기 때문이다.
type Props = {
hello: string
}
function HelloComponent{props: Props){
return <h1> {hello} </h1>
}
function App() {
return <HelloComponent hello = "hi!" />
}
깊은 비교를 제공하지 않는 이유는 props가 객체 안에 객체가 몇개 있을지 알 수 없기에 재귀적으로 비교할 경우 악영향을 미치기 때문이다.
'프론트엔드' 카테고리의 다른 글
Next js 정리 2. 라우팅 시스템과 내장 컴포넌트 (0) | 2024.04.08 |
---|---|
Next Js 정리 1. 렌더링 전략 (0) | 2024.04.08 |
모던리액트딥다이브 1. 이벤트루프와 비동기 통신 이해 (0) | 2024.03.28 |