JSX는 JavaScript XML이라는 의미를 담고 있다. JavaScript를 확장한 문법이다.
JSX는 XML/HTML과 Syntax가 비슷하면서 리액트에서 사용되는 문법이다. 즉, 자바스크립트/React 코드와 공존할 수 있도록 ECMAScript를 확장한 코드라고 할 수 있다.
JSX는 자바스크립트 파일에 있는 HTML 같은 텍스트들을 자바스크립트 엔진이 파싱할 수 있는 표준 자바스크립트 객체로 변환하기 위해 Babel과 같은 프리프로세서에 의해 사용되도록 의도되었다.
EJS와 같은 템플릿 언어와 큰 차이점은 EJS는 트랜스파일링과정을 거치면 HTML파일로 변환되지만 JSX는 자바스크립트 파일로 변환된다는 점이다.
즉 JSX를 사용하면 자바스크립트 코드를 작성할 때랑 같은 파일에 HTML/XML(돔트리 구조와 비슷한)을 작성할 수 있고, 브라우저에서 실행되기 전에 번들링 과정에서 Babel은 JSX를 자바스크립트 코드로 변환한다.
// JSX
function App(){
return (
<div>
Hello <b>react</b>
</div>
);
}
이렇게 작성된 JSX는 다음과 같이 변환된다.
React.createElement(
type, 태그 이름 문자열 | React 컴포넌트 | React.Fragment
[props], // 리액트 컴포넌트에 넣어주는 데이터 객체
[...children] // 자식으로 넣어주는 요소들
);
function App(){
return React.createElement('div', null, 'Hello ', React.createElement('b', null, 'react'));
}
위의 코드와 같이React.createElement
라는 메서드를 통해 요소(element)를 생성해야 한다면, 요소의 depth나 갯수만큼 사용해야 한다. 하지만 위의 JSX코드는 HTML형식을 지니고 있어서 가독성이 매우 좋다.
// 1. 리액트 컴포넌트 -> HTMLElement 연결하기
import ReactDOM from 'react-dom';
// 2. 리액트 컴포넌트 만들기
import React from 'react';
ReactDOM.render
이 코드는 컴포넌트를 페이지에 렌더링하는 역할을 하고, react-dom 모듈을 불러와야 사용할 수 있다. 프로그램의 진입의 역할을 하는 Main()의 역할을 담당하는 함수라고 볼 수도 있다. 첫 번째 파라미터에는 페이지에 렌더링할 내용을 JSX형태로 작성하고, 두 번째 파라미터에는 해당 JSX를 렌더링할 document 내부 요소를 설정한다.
즉, 만들어진 리액트 컴포넌트를 실제 HTMLElement에 연결할 때 ReactDOM 라이브러리를 이용한다.
ReactDOM.render(
React.createElement(Component, null, null), // what
document.querySelector('#root'), // where
);
import React from 'react';
function App() {
return (
<h1>Hello react</h1>
<h2>Bye react</h2>
);
}
export default App;
위의 코드는 에러를 발생시킨다. 부모 요소에 의해 래핑되어 있지 않아서 생긴 오류인데 다음과 같이 해결할 수 있다.
import React from 'react';
function App() {
return (
<div>
<h1>Hello react</h1>
<h2>Bye react</h2>
</div>
);
}
export default App;
Virtual DOM에서 컴포넌트 변화를 감지할 때 효율적으로 비교할 수 있게 컴포넌트는 하나의 DOM 트리로 이루어져 있어야 한다는 규칙때문이다. 하지만 불필요한 태그를 생성하는 것은 좋지 않으므로,
import React, {Fragment} from 'react';
function App(){
return (
<Fragment>
<h1>Hello react</h1>
<h2>Bye react</h2>
</Fragment>
)
}
export default App;
function App(){
return (
<>
<h1>Hello react</h1>
<h2>Bye react</h2>
<>
);
}
두가지의 방법으로 표현하여 해결할 수 있다.
JSX 내부에서는 자바스크립트 표현식을 사용할 수 있다. 자바스크립트 표현식을 작성하려면 JSX 내부에서 코드를 { }로 감싸야 한다.
import React from 'react';
function App(){
const name = 'React';
return (
<>
<h1>Hello {name}</h1>
<h2>Bye react</h2>
</>
);
}
JSX의 {}에서 if문을 사용할 수 없다. if문은 표현식이 아닌 문이기 떄문이다. 따라서 if문을 쓰기보다는 삼항 연산자를 사용한다.
function App(){
const name = 'React';
return (
<>
{name === 'React' ? (<h1>리액트입니다</h1>) : (<h2>리액트가 아닙니다</h2>)}
</>
);
}
렌더링 할 컴포넌트가 없다면 명시적으로 null을 적어주자!
function App() {
const name = "REEACT";
return <div>{name === 'React' && <h1>리액트입니다.</h1>}</div>;
}
다음과 같이 조건부로 렌더링을 해줄 수 있다.
주의할 점은 falsy한 값이 오면 0이 렌더링된다.
리액트 컴포넌트에서는 함수에서 undefined만 반환하여 렌더링하는 경우를 피해야한다.
function App() {
const name = undefined;
return name;
}
다음 코드는 브라우저에서 오류를 발생시킨다. 이런 상황을 OR(||) 연산자를 사용하여 해결할 수 있다.
function App() {
const name = undefined;
return name || '값이 undefined입니다';
}
그러나 JSX 내부에서 undefined를 렌더링하는 것은 괜찮다.
function App() {
const name = undefined;
return <div>{name || 'react'}</div>
}
리액트에서 DOM 요소에 스타일을 적용할 때는 객체 형태로 넣어야한다. -이 들어가는 문자는 카멜 케이스를 이용하여 작성해야한다.
ex) backgroundColor
function App() {
const name = 'React';
const style = {
backgroundColor : 'black',
color : 'aqua',
fontSize : '48px',
padding : 16 // 단위를 생략하면 px로 인지한다.
};
return <div style = {style}>{name} </div>;
}
미리 style을 지정하지 않고 바로 선언하고 싶다면 {{}}을 이용하여 작성한다.
function App() {
const name = 'React';
return (
<div style = {{
backgroundColor : 'black',
color : 'aqua',
fontSize : '48px',
padding : 16 // 단위를 생략하면 px로 인지한다.
}}>
{name}
</div>
);
}
❗️ 주의할 점은 리액트는 이전 상태와 현재 상태를 비교하여 렌더링을 다시 시키는데 변수로 지정하지 않고 바로 객체 리터럴을 넣어준다면 렌더링할 때 마다 함수를 호출하게 되고 함수내부에서 새로운 참조값의 객체가 새로 생기게 되므로 불필요한 리렌더링이 일어날 가능성이 있으므로 변수로 선언해서 넣어주는 걸 지향하자.
HTML에서 CSS클래스를 사용할 때는 class
라는 키워드를 사용하는데 JSX에서는 className으로 설정해 주어야 한다.
.react {
background-color: aqua;
color: black;
font-size: 48px;
font-weight: bold;
padding: 16px;
}
import './App.css';
function App() {
const name = 'React';
return <div className="react">{name}</div>;
}
<input>
요소는 <input>
이라고만 입력해도 동작한다. 하지만 JSX 에서는 오류를 발생시킬 수 있다.
function App() {
const name = '리액트';
return (
<>
<div className="react">{name}</div>
<input>
</>
);
}
다음 오류를 해결하려면 <input></input>
이와 같이 태그를 닫아주어야 한다. 태그에 별도의 내용이 들어가지 않는 경우에는 <input />
과 같이 작성할 수도 있다.