[React] JSX(JavaScript and XML)
1. JSX(JavaScript and XML)
- 자바스크립트와 XML/HTML을 함께 사용할 수 있는 자바스크립트의 확장 문법
// HTML의 <h1>태그를 사용한 Hello, world!라는 문자열을 값으로 가지고있는 것을 const형의 element 변수에 대입
const element = <h1>Hello, world!</h1>;
- 내부적으로 XML/HTML 코드를 자바스크립트로 변환하는 과정을 거침
- 리액트의 createElement() 함수는 JSX코드를 자바스크립트 코드로 변환해주는 역할을 함
-> JSX코드를 작성해도 최종적으로 자바스크립트 코드가 나옴
2. JSX의 역할
1) JSX로 작성된 코드는 모두 자바스크립트 코드로 변환
JSX로 작성한 코드와 순수 자바스크립트로 작성한 코드 비교
- JSX로 작성한 코드
// Hello라는 이름을 가진 리액트 컴포넌트, 컴포넌트 내부에서 자바스크립트 코드와 HTML 코드가 결합된 JSX사용
class Hello extends React.Component {
render() {
return <div>Hello {this.props.toWhat}</div>;
}
}
// 위에서 만들어진 컴포넌트를 ReactDOM의 render()함수를 사용해서 실제 화면에 렌더링
ReactDOM.render(
<Hello towhat="World" />,
document.getElementById('root')
);
- 순수 자바스크립트로 작성한 코드
class Hello extends React.Component {
render() {
// JSX를 사용했던 부분이 React.createElement()라는 함수로 대체
return React.createElement('div', null, 'Hello ${this.props.toWhat}');
}
}
ReactDOM.render(
React.createElement(Hello, {towhat:'World'}, null),
document.getElementById('root')
);
-> JSX를 사용했을 때 코드가 더욱 간결해지고 생산성과 가독성이 올라가기 때문에 JSX 사용을 권장
cf) ReactDOM.render
ReactDOM.render 코드는 컴포넌트를 페이지에 렌더링하는 역할을 하며 react-dom 모듈을 불러와 사용할 수 있다.
이 함수의 첫 번째 파라미터에는 페이지에 렌더링할 내용을 JSX 형태로 작성하고, 두 번째 파라미터에는 해당 JSX를 렌더링할 document 내부 요소를 설정한다.
위에서는 id가 root인 요소 안에 렌더링을 하도록 설정한 코드이다.
이 요소는 public/index.html 파일을 열어보면 확인할 수 있다.
2) JSX를 사용한 코드는 내부적으로 createElement()함수를 사용하도록 변환되기 때문에 자바스크립트 객체가 나오게 됨
// JSX를 사용한 코드
const element = (
<h1 className="greeting">
Hello, world!
</h1>
)
// JSX를 사용하지 않은 코드
const element = React.createElement(
'h1',
{ className: 'greeting' },
'Hello, world!'
)
리액트에서는 createElement() 함수의 결과인 자바스크립트 객체를 엘리먼트라고 부름
(createElement는 element를 생성해서 리턴)
element() 함수
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
}
element()함수의 파라미터
React.createElement (
type, // 엘리먼트 유형(type): <div>, <span> 같은 HTML 태그, 리액트 컴포넌트가 들어갈 수 있음
[props], // 속성
[...children] // children: 현재 엘리먼트가 포함하고 있는 자식 엘리먼트
)
3. JSX의 장점
1) 코드가 간결해짐
// JSX 사용함
<div>Hello, {name}</div>
// JSX사용안함
React.createElement ('div', null, 'Hello, ${name}');
2) 가독성 향상
3) Injection Attack 이라 불리는 해킹 방법을 방어함으로써 보안성 상승
Injection Attack: 입력창에 문자나 숫자 같은 일반적인 값이 아닌 소스코드를 입력하여 해당 코드가 실행되도록 만드는 해킹 방법
// title이라는 변수에 잠재적으로 보안 위험의 가능성이 있는 코드가 삽입되어 있음
const title = response. potentiallyMaliciousInput;
// 괄호를 사용해서 title 변수를 임베딩(삽입)
const element = <h1›{title}</h1>;
기본적으로 ReactDOM은 렌더링 전에 임베딩 값을 모두 문자열로 변환함
-> 명시적으로 선언되지 않은 값은 괄호 사이에 들어갈 수 없음
-> XSS(cross-site-scripting attacks)를 방어할 수 있음
4. JSX 사용법
1) 기본적으로 모든 자바 스크립트 문법 지원
2) 자바스크립트에 XML과 HTML 섞어서 사용
3) 중괄호를 사용하여 자바 스크립트 코드 삽입 -> 데이터 바인딩
const name = 'sky';
/* 엘리먼트 선언, HTML과 자바스크립트가 섞인 형태로 코드 작성
* XML/HTML 코드를 사용하다가 중간에 자바스크립트 코드 사용할 부분에 중괄호 '{}' 로 묶어주면 됨
*/
const element = <h1>안녕, {name}</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);
4) 인라인 스타일링
<h1 style={{color : 'red', fontSize : '16px'}}>제목</h1>
5) 감싸인 요소
컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 함
이유: Virtual DOM에서 컴포넌트 변화를 감지해 낼 때 효율적으로 비교할 수 있도록 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문
// 컴파일 에러 발생, 요소 여러 개가 부모 요소 하나에 감싸져 있지 않음
import React from 'react';
function App() {
return (
<h1>리액트 안녕!</h1>
<h2>잘 작동하니?</h2>
)
}
export default App;
// 규칙이 적용된 코드, <div> 태그 사용
import React from 'react';
function App() {
return (
<div>
<h1>리액트 안녕!</h1>
<h2>잘 작동하니?</h2>
</div>
);
}
export default App;
// 규칙이 적용된 코드, <Fragment> 사용( '<>'로 간략하게 표현 가능)
import React, { Fragment } from 'react';
function App() {
return (
<Fragment>
<h1>리액트 안녕!</h1>
<h2>잘 작동하니?</h2>
</Fragment>
);
}
export default App;
6) If문 대신 조건부 연산자(삼항 연산자)사용
JSX 내부의 자바스크립트 표현식에서 if문은 사용할 수 없지만 조건에 따라 다른 내용을 렌더링해야 할 때는 JSX 밖에서 if문을 사용하여 사전에 값을 설정하거나, { } 안에 조건부 연산자를 사용하면 됨
import React from 'react';
function App() {
const name = '리액트';
return (
<div>
{name === '리액트' ? (
<h1>리액트입니다.</h1>
) : (
<h2>리액트가 아닙니다.</h2>
)}
</div>
);
}
export default App;
7) AND 연산자(&&)을 사용한 조건부 렌더링
& 연산자로 조건부 렌더링 할 수 있는 이유는 리액트에서 flase를 렌더링할 때는 null과 마찬가지로 아무것도 나타나지 않기 때문임
import React from 'react';
function App() {
const name = '리액트';
return <div>{name === '리액트' && <h1>리액트입니다.</h1>}</div>;
}
export default App;
한 가지 주의해야할 점은 falsy한 값인 0은 예외적으로 화면에 나타남
const number = 0;
return number && <div>내용</div>
4. JSX 주의사항
1) undefined를 렌더링하지 않기
// App(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
// 에러 발생
import React from 'react';
import './App.css';
function App() {
const name = undefined;
return name;
}
export default App;
에러 발생을 막기 위해서 OR(||) 연산자 이용
어떤 값이 undefined일 수 있다면 사용할 값을 지정할 수 있음
import React from 'react';
import './App.css';
function App() {
const name = undefined;
return name || '값이 undefined입니다.';
}
export default App;
JSX 내부에서 undefined를 렌더링하는 것은 가능