이 글은
라는 물음으로 부터 시작되었다 !
리액트에서 특정 조건에따라 컴포넌트를 조건부 렌더링할때,
조건이 boolean 타입일때는 명확하지만,
해당 변수에 값이 있는지 여부로 조건부 렌더링할때는 항상 이게 되나..? 하면서 넘어갔던 것 같아서
정확히 짚고 넘어가려고 한다.
interface IUserInfoProps {
id: string;
name: string;
purchasedProductList?: string[];
}
const UserInfo: React.FC<IUserInfoProps> = ({ id, name, purchasedProductList }) => {
return (
<div>
<p>{id}</p>
<p>{name}</p>
{purchasedProductList.map((purchasedProduct)=><p>purchasedProduct</p>)}
</div>
);
};
const Test = () => {
const [id, setId] = useState('1');
const [name, setName] = useState('euneun');
const [purchasedProductList, setPurchasedProductList] = useState(['펜','지우개','연필']);
useEffect(() => {}, []);
return <UserInfo id={id} name={name} />;
};
예를 들어 위의 상황에서 purchasedProductList
속성은 optional이기 때문에, 컴포넌트에 전달 되었을수도, 아닐수도있다.
따라서 저런 상황일때 우린 TS2532: Object is possibly 'undefined'
라는 타입스크립트 에러를 마주하게 되는데,
{purchasedProductList?.map((purchasedProduct)=><p>purchasedProduct</p>)}
와 같이 optional chaining 을 이용해서 간단하게 해결 할 수 있지만,
그건 조금 이따가 살펴보기로 하고
습관적으로 다음과같이 &&
로 조건부 렌더링 하는 경우를 살펴보자.
{purchasedProductList && purchasedProductList.map((purchasedProduct)=><p>purchasedProduct</p>)}
purchasedProductList
는 true
나 false
값이 아닌데 왜 당연하게도 이렇게 사용해왔을까에 대한 의문이 갑자기 들었다.
Falsy한 값이란 ?
위에 예시상황의boolean
을 기대하는 문맥에서처럼 , 거짓으로 평가되는 값이다!
MDN에서는 위의 8가지 값을falsy
한 값이라고 정의했는데,
0
과false
는 관습적으로 알 수 있는 내용이고
💡빈 string
,null
,undefined
,NaN
💡 이 falsy한 값이라는 것에 유의해서 보면 좋을 것 같다!
예를 들어 아래와 같은 댓글창을 만들때,
인풋 값이 있냐 없냐에 따라 댓글작성 버튼의 disabled
여부를 정한다고 하면
빈 string
은 falsy
한 값이기 때문에 아래 코드와 같이 해주면 작동된다.
const [name, setName] = useState('');
return (
<>
<input onChange={(e) => setName(e.target.value)} />
<button disabled={!name} />
</>
);
또한 위에서
{purchasedProductList && purchasedProductList.map((purchasedProduct)=><p>purchasedProduct</p>)}
이 코드가 작동한 이유도,
purchasedProductList
가 undefined
일때는 falsy
한 값으로 되어,
&&
뒤의 엘리먼트는 React가 무시하게 된것이다.
이렇게 undefined
와 null
은 falsy
한 값이라서 not을 해주면 true
가 되기때문에
if문에 들어오게되어, 콘솔에 hi가 찍히는 것을 알 수 있다!
내가 습관적으로 하고 있었던것이 falsy
, truthy
한 값이라서 그렇게 작동하고 있었다는게 신기했다!
{purchasedProductList && purchasedProductList.map((purchasedProduct)=><p>purchasedProduct</p>)}
falsy
한 값들 중 undefined
, null
, 빈 string
의 경우말고 0
일 경우도 살펴보자
render() {
const count = 0;
return (
<div>
{ count && <h1>Messages: {count}</h1>}
</div>
);
}
아무것도 렌더링되지 않는것이 아니라,
0이 렌더링 된것을 확인 할 수 있다.
console.log(0 && 'hi')
이렇게 알 수 있듯이
falsy
표현식을 반환하면 여전히&&
뒤에 있는 표현식은 건너뛰지만falsy
표현식이 반환된다는 것에 주의해야 한다.
그동안 falsy
한 0
에 대해 다룰 일은 없었고,
undefined
, null
, ''(빈 string)
값을 주로 조건부 렌더링 시켜서
결국 undefined
,null
,빈 string
이 반환되어 화면에 렌더링 되었던건데
아무것도 렌더링 하지 않았다고 착각하고 있었다.
그리고
null
과undefined
는 엄연히 다르다는것을 명심해야한다!
{purchasedProductList?.map((purchasedProduct)=><p>purchasedProduct</p>)}
TypeScript 3.7부터 추가된 optional chianing을 이용하면 위와 같이 쓸 수 있다.
?
앞에있는 purchasedProductList
가 undefined
또는 null
일때는 그 이후의 속성을 찾지 않고, 바로 undefined
를 반환하게된다.
&&
를 쓸때보다 코드가 훨씬 간단해진다는 장점이 있다.
MDN에서 설명하는 &&
와 ?.
연산자의 정의를 찾아보면, 아래와 같이 설명하고 있다.
&&
- More generally, the operator returns the value of the first falsy operand encountered when evaluating from left to right, or the value of the last operand if they are all truthy.
-> 반적으로&&
연산자는 왼쪽에서 오른쪽으로 평가할 때 처음 발생한falsy
피연산자 값을 반환하거나 모두truthy
인 경우 마지막 피연산자의 값을 반환합니다.
-> 왼쪽이false
면, 오른쪽은 볼 것도 없이 왼쪽 값을 반
환한다 !!!
?.
?.
연산자는.
체이닝 연산자와 유사하게 작동하지만, 만약 참조가nullish
(en-US) (null
또는undefined
)이라면, 에러가 발생하는 것 대신에 표현식의 리턴 값은undefined
로 단락된다. 함수 호출에서 사용될 때, 만약 주어진 함수가 존재하지 않는다면,undefined
를 리턴한다.
한마디로, ?.
는 nullish(null
또는 undefined
)한지를 보고,
&&
는 falsy
한지를 본다는점이 다르다!
return (
<div>
{ balance && <h1>잔액: {balance}원</h1>}
</div>
);
내 실제 잔액으로 받은 balance
값이 0원인데,
위에와 같이 &&
를 이용해서 조건부렌더링하면 잔액:0원
이 뜨는게 아니라
0
이 falsy
한 값이기 때문에 falsy
표현식이 반환되어서0
만 렌더링 되게 되는 문제점이 있었다.
이러한 오류를 방지하기 위해 nullish operator(??
)를 사용할 수 있다.
??
연산자는, 왼쪽 피연산자가null
또는undefined
일 때 오른쪽 피연산자를 반환하고, 그렇지 않으면 왼쪽 피연산자를 반환하는 논리 연산자이다.
falsy
인지 확인하지않고 null
또는 undefined
인지만 확인해서 예기치 않는 동작이 발생할수있는 상황을 줄인다!
// balance가 undeinfed or null 이면 잔액 0원과 다름없다는것을 가정
return (
<div>
<h1>잔액: {balance ?? 0}원</h1>
</div>
);
다음과 같이 작성하면 내가 의도한대로 balance가 0일때,
0
이 falsy
한값이든말든 그건 중요하지않고
0
은 Null
이나 undefined
가 아니기때문에
왼쪽 피연산자인 balance
를 정상적으로 반환하여 잔액:0원
이 뜨게된다.
참고