JSX — HTML처럼 생겼지만 자바스크립트다
Article
앞 강의에서 return <h1>안녕</h1>;이라고 썼다. 자바스크립트에 이런 문법은 없다.
이게 JSX다. 이름은 JavaScript XML의 줄임말이고, 정체는 자바스크립트다.
실제로는 함수 호출이다
빌드 도구가 JSX를 무엇으로 바꾸는지 보면 오해가 사라진다.
const element = <h1 className="title">안녕</h1>;
이 코드는 변환을 거쳐 이렇게 된다.
const element = React.createElement("h1", { className: "title" }, "안녕");
그리고 createElement가 돌려주는 건 그냥 객체다.
{
type: "h1",
props: { className: "title", children: "안녕" }
}
- <h1>안녕</h1>우리가 쓰는 것
- createElement()빌드 도구가 바꾼다
- 자바스크립트 객체React 가 다루는 것
이 사실을 알면 나머지가 전부 설명된다. JSX는 값이다. 변수에 담고, 배열에 넣고, 함수가 반환할 수 있다.
const title = <h1>안녕</h1>;
const list = [<li>하나</li>, <li>둘</li>];
function getTitle() {
return <h1>안녕</h1>;
}
자바스크립트 편 11강에서 "함수는 값이다"라고 했던 것과 같은 이야기다.
중괄호 — 자바스크립트로 돌아가는 문
JSX 안에서 자바스크립트를 쓰려면 중괄호를 연다.
function Greeting() {
const name = "지원";
const age = 27;
return (
<div>
<h1>안녕, {name}</h1>
<p>내년이면 {age + 1}살</p>
<p>{name.toUpperCase()}</p>
<p>{age >= 19 ? "성인" : "미성년자"}</p>
</div>
);
}
중괄호 안에는 값이 되는 것이라면 무엇이든 들어간다. 변수, 계산식, 함수 호출, 삼항 연산자.
들어갈 수 없는 것도 있다.
가능
값이 되는 것 (표현식)
{name}— 변수{age + 1}— 계산식{getName()}— 함수 호출{a ? b : c}— 삼항 연산자{list.map(...)}— 메서드 체이닝
불가능
값이 안 되는 것 (문)
{if (a) {...}}— if 문{for (...) {...}}— for 문{const x = 1}— 변수 선언- 삼항 연산자나
map으로 바꿔 쓴다
if문은 값을 만들지 않고 실행만 한다. 그래서 중괄호에 넣을 수 없다. 자바스크립트 편 8강에서 "if문은 실행하고, 삼항 연산자는 값을 낸다"고 구분한 이유가 여기서 드러난다.
무엇이 화면에 보이나
중괄호에 넣은 값의 타입에 따라 화면에 나오는 게 다르다. 헷갈리는 부분이다.
function Test() {
return (
<div>
<p>{42}</p>
<p>{"글자"}</p>
<p>{true}</p>
<p>{null}</p>
<p>{undefined}</p>
<p>{[1, 2, 3]}</p>
<p>{0}</p>
</div>
);
}
| 값 | 화면에 | 비고 |
|---|---|---|
| 42 | 42 | 숫자는 그대로 |
| "글자" | 글자 | 문자열도 그대로 |
| true / false | (아무것도 안 나옴) | boolean 은 무시된다 |
| null / undefined | (아무것도 안 나옴) | 무시된다 |
| [1, 2, 3] | 123 | 배열은 펼쳐서 이어붙인다 |
| 0 | 0 | 숫자라서 보인다 — 주의 |
마지막 줄이 함정이다. 자바스크립트 편 7강에서 0이 falsy라고 배웠는데, React는 0을 화면에 그린다.
function Cart({ items }) {
return <div>{items.length && <p>담긴 상품이 있다</p>}</div>;
}
items가 빈 배열이면 items.length는 0이다. 0 && ...은 0을 돌려주고(자바스크립트 편 6강의 단축 평가), React는 그 0을 화면에 찍는다. 아무것도 없어야 할 자리에 0이 나타난다.
HTML 과 다른 점
JSX는 자바스크립트라서 HTML과 어긋나는 지점이 있다.
class 가 아니라 className
class는 자바스크립트의 예약어다. 자바스크립트 편 19강에서 클래스를 만들 때 쓴 그 키워드다. 그래서 이름을 바꿨다.
<div className="card">…</div>
같은 이유로 for도 htmlFor가 된다.
속성은 카멜 케이스
| HTML | JSX | 이유 |
|---|---|---|
| class | className | class 는 예약어 |
| for | htmlFor | for 는 예약어 |
| onclick | onClick | 카멜 케이스 |
| tabindex | tabIndex | 카멜 케이스 |
| maxlength | maxLength | 카멜 케이스 |
data-*와 aria-*는 예외다. 하이픈 그대로 쓴다.
모든 태그를 닫는다
HTML에서 허용되던 열린 태그가 JSX에서는 에러다.
<br />
<img src="a.png" alt="" />
<input type="text" />
<br>이 아니라 <br />이다. XML 규칙을 따르기 때문이다.
스타일은 객체로
<div style={{ color: "red", fontSize: "16px" }}>빨강</div>
중괄호가 두 개다. 바깥은 JSX의 중괄호, 안쪽은 객체 리터럴의 중괄호다.
속성명도 카멜 케이스다. font-size는 fontSize가 된다. 하이픈은 자바스크립트에서 뺄셈으로 읽히기 때문이다.
흔히 만나는 실수
- 01
return 뒤에 줄바꿈
자바스크립트가 세미콜론을 자동으로 넣어
undefined를 반환해버린다. 여러 줄이면 괄호로 감싼다.return ( <div>…</div> ); - 02
주석은 중괄호 안에
JSX 안에서
//는 화면에 글자로 찍힌다.{/* 이렇게 쓴다 */} - 03
중괄호 안에 문을 넣기
if나for는 값이 아니다. 삼항이나map으로 바꾼다.{isLogin ? <Home /> : <Login />}
첫 번째는 정말 자주 겪는다.
function App() {
return
<h1>안녕</h1>;
}
return 뒤에서 문장이 끝난 것으로 처리되어 아무것도 반환하지 않는다. 자바스크립트 편 2강에서 "세미콜론을 자동으로 붙여준다"고 했던 게 여기서 사고를 친다.
정리하면
- JSX는 HTML이 아니다.
createElement()호출로 바뀌고, 결과는 자바스크립트 객체다. - 그래서 JSX는 값이다. 변수에 담고 함수가 반환한다.
- 중괄호 안에는 값이 되는 것만 넣는다.
if나for는 못 넣는다. boolean,null,undefined는 화면에 안 나오지만0은 나온다.&&앞에 숫자를 두지 않는다.class→className, 속성은 카멜 케이스, 모든 태그를 닫는다.return뒤에 줄을 바꾸려면 괄호로 감싼다.
다음 강의부터 Part 2다. 컴포넌트를 어떤 기준으로 나누는지 본다.