React

[2장 JSX] JSX문법

일등하이 2020. 11. 19. 17:18
반응형

감싸인 요소

컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 한다 

한번 App.js파일의 App컴포넌트 함수 내부를 지우고 다음과 같이 작성해 보자 

상단에 있는 SVG와 CSS를 import하는 부분도 지우자 

코드를 저장한 후 웹브라우저나 개발 서버를 실행했던 터미널을 열어보면 다음과 같은 에러가 날것이다 

요소여러개가 부모요소 하나에 의하여 감싸져 있지 않기 때문이다 

다음과 같이 작성해서 해결하자 

import React from 'react';

function App() {
  return(
    <div>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </div>
  );
}

export default App;

 

리액트 컴포넌트에서 요소 여러 개를 왜 하나의 요소로 꼭 감싸줘야 하는가?

그것은 VirtualDOM에서 컴포넌트 변화를 감지해 낼때 효율적으로 비교 할수 있도록 컴포넌트 내부는 하나의 DOM트리 구조로 이루어져야 한다는 규칙이 있기 때문이다 

www.youtube.com/watch?v=BYbgopx44vo

 

그런데 여기서 꼭 div요소를 사용하고 싶지 않을수도 있다 

그런경우 리액트 v16이상부터 도입된 Fragment라는 기능을 사용하면된다 

ko.reactjs.org/docs/fragments.html

 

Fragments – React

A JavaScript library for building user interfaces

ko.reactjs.org

velog.io/@lilyoh/React-Fragments-%EC%82%AC%EC%9A%A9%EC%9D%B4%EC%9C%A0-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95

 

React Fragments 사용이유 및 사용법

리액트에서는 하나의 컴포넌트가 여러 개의 엘리먼트들을 반환한다. 리액트를 사용하기 위한 문법인 JSX 를 쓸 때, return 문 안에는 반드시 하나의 최상위 태그가 있어야 한다. 이는 리액트가 하

velog.io

import React, { Fragment } from 'react';


function App() {
  return(
    <Fragment>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </Fragment>
  );
}

export default App;

import구문에서 react모듈에 들어 있는 Fragment라는 컴포넌트를 추가로 불러온다 

Fragment는 다음과 같은 형태로도 표현 할수 있다 

import React, { Fragment } from 'react';


function App() {
  return(
    <>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </>
  );
}

export default App;

 

 

자바스크립트 표현 

JSX가 단순히 DOM요소를 랜더링 하는 기능밖에 없다면 뭔가 좀 아쉬웠을 것이다 

JSX안에서는 자바스크립트 표현식을 쓸수 있다 

자바스크립트 표현식을 작성하려면 JSX내부에서 코드를 {  }로 감싸주면 된다 

자바스크립트 값을 JSX안에서 한번 랜더링 해보자 

import React, { Fragment } from 'react';


function App() {
  const name = '리액트';
  return(
    <>
      <h1>{name} 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </>
  );
}

export default App;

 

 

ES6의 const와 let

const는 ES6문법에서 새로 도입되었다 

한번 지정하고 나면 변경이 불가능한 상수를 선언할때 사용하는 키워드이다 

let은 동적인 값을 담을수 있는 변수를 선언할때 사용하는 키워드이다 

ES6이전에 값을 담는데는 var키워드를 사용했다 

var 키워드는 scope(해당 값을 사용할수 있는 코드 영역)이 함수 단위 였다 

function myFunction(){
    var a = "hello";
    if(true){
        var a = "bye";
        console.log(a);
    }
    console.log(a);
}

myFunction();

if문 바깥에서 var값을 hello로 선언하고 if문 내부에 bye로 설정했다 

if문 내부에서 새로 선언했음에도 if문밖에서 a를 조회 하면 변경된 값이 출력된다 

이런 결점을 해결해주는 것이 바로 const와 let이다 

function myFunction(){
    let a = 1;
    if(true){
        let a = 2;
        console.log(a);
    }
    console.log(a);
}

myFunction();

const와 let은 scope가 함수단위가 아닌 블럭단위이다 

if문 내부에서 선언한 a값은 if문 밖에의 a값을 변경하지 않는다 

let과 const를 사용할때 같은 블럭 내부에서 중복 선언이 불가능 하다 

const는 한번 선언하면 값을 재설정 할수 없다 

일단 ES6문법에서 var를 사용할일은 없다 

let은 선언한후 값이 유동적으로 변할수 있을때 (ex: for문)

const는 한번 설정한후 변할일이 없는 값에 사용한다 

편하게 생각하면 기본으로 const를 사용하고 해당값을 변경해야 할때 let을 사용한다 

 

 

If문 대신 조건부 연산자 

JSX내부의 자바스크립트 표현식에서 if문을 사용할수 없다 

하지만 조건에 따라 다른 내용을 랜더링 해야 할때 JSX밖에서 if문을 사용하여 사전에 값을 설정 하거나 ,

{ } 조건부 연산자를 사용한다 

조건부 연산자의 또 다른 이름은 삼항 연산자 이다 

이 연산자를 한번 사용해 보자 

import React, { Fragment } from 'react';


function App() {
  const name = '리액트';
  return(
    <div>
      {
        name === '리액트' ? (<h1>리액트입니다.</h1>) : (<h2>리액트가 아닙니다.</h2>)
      }
    </div>
  );
}

export default App;

이렇게 코드를 작성한 후 저장하면 브라우저에서 '리액트입니다' 라는 문구를 볼수 있다 

name의 값을 다른것으로 변경하면 '리액트가 아닙니다' 라는 문자열이 출력 된다.

import React, { Fragment } from 'react';


function App() {
  const name = '리웻트';
  return(
    <div>
      {
        name === '리액트' ? (<h1>리액트입니다.</h1>) : (<h2>리액트가 아닙니다.</h2>)
      }
    </div>
  );
}

export default App;

 

 

 

AND 연산자 (&&)를 사용한 조건부 렌더링 

특정조건을 만족할때 내용을 보여주고 만족하지 않을때 아무런것도 렌더링 하지 않아야 하는 상황이 올수 있다 

이럴때도 조건부 연산자를 통해 구현 할수 있다 

import React from 'react';


function App() {
  const name = '리액트';
  return <div>{ name === '리액트' ? <h1>리액트입니다.</h1> : null }</div>
}

export default App;

 

위코드와 같이 null을 랜더링 하면 아무것도 보여주지 않는다 

하지만 이것보다 더 짧은 코드로 똑같은 작업을 할수 있다 

다음과 같이 &&연산자를 사용해서 조건부 렌더링을 할수 있다 

developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Expressions_and_Operators#%EB%85%BC%EB%A6%AC_%EC%97%B0%EC%82%B0%EC%9E%90

 

표현식과 연산자

이 장은 JavaScript의 표현식과 할당, 비교, 산술, 비트 계산, 논리, 문자열, 삼항 등 여러 가지 연산자를 설명합니다.

developer.mozilla.org

import React from 'react';


function App() {
  const name = '리액트';
  return <div>{name === '리액트' && <h1>리액트입니다.</h1>}</div>
}

export default App;

&&연산자로 조건부 렌더링을 할수 있는 이유는 false를 렌더링 할때 null과 마찬가지로 아무것도 나타나지 않기 때문이다 

여기사 한가지 주의 해야 할 점이 있다 

false한 값인 0은 예외적으로 화면에 나타난다는것이다 

import React from 'react';


function App() {
  const num = 0;
  return num && <div>내용</div>
}

export default App;
이코드는 화면에 숫자 0을 보여준다 

 

JSX는 언제 괄호로 감싸야 하나?

JSX를 작성할때 

(<div>Hello World</div>) 

와 같이 괄호로 감쌀때도 있고, 감까지 않을때도 있다 

주로 JSX를 여러줄로 작성할때 괄호로 감싸고, 한줄로 표현 할수 있는 JSX는 감싸지 않는다 

 

 

undefined를 렌더링 하지 않기 

developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/undefined

 

undefined

전역 undefined 속성은 undefined 원시 값을 나타내며, JavaScript의 원시 자료형 중 하나입니다.

developer.mozilla.org

리액트 컴포넌트에서는 함수에서 undefined만 반환하여 렌더링 하는 상황을 만들면 안된다 

예를들어 다음과 같은 코드는 오류를 발생시킨다 

import React from 'react';


function App() {
  const name = undefined;
  return name;
}

export default App;

코드를 저장한후 브라우저를 확인해보면 다음과 같은 오류를 볼수 있다 

어떤 값이 undefined일수 있다면, OR(||)연산자를 사용하면 해당 값이 undefined일때 사용할 값을 지정할수 있으므로 간단하게 오류를 방지할 수 있다.

import React from 'react';


function App() {
  const name = undefined;
  return name || '값이 undefined입니다.';
}

export default App;

반면 JSX내부에서 undefined를 렌더링 하는것은 괜찮다 

import React from 'react';


function App() {
  const name = undefined;
  return <div>{name}</div>
}

export default App;

name 값이 undefined일때 보여주고 싶은 문구가 있다면 다음과 같이 코드를 작성 하면된다 

import React from 'react';


function App() {
  const name = undefined;
  return <div>{name || '리액트'}</div>
}

export default App;

 

 

 

인라인 스타일링

리액트에서 DOM요소에 스타일을 적용할 때는 문자열 형태로 넣는것이 아니라 객체 형태로 넣어줘야 한다 

스타일 이름중에 background-color처럼 - 문자가 포함되는 이름이 있다 

이러한 이름은 - 문자를 없애고 카멜 표기법으로 작성 해야 한다 

따라서 background-color는

backgroundColor

로 작성 한다 

 

developer.mozilla.org/ko/docs/Web/CSS/padding

 

padding

padding CSS 속성은 요소의 네 방향 안쪽 여백 영역을 설정합니다. padding-top, padding-right, padding-bottom, padding-left의 단축 속성입니다.

developer.mozilla.org

import React from 'react';


function App() {
  const name = '리액트';
  const style = {
    backgroundColor: 'black',
    color: 'aqua',
    fontSize: '48px',
    fontWeight: 'bold', 
    padding: 16   //단위를 생략하면 px로 지정된다 
  };
  return <div style={style}>{name}</div>
}

export default App;

style객체를 미리 선언하고 div의 style값으로 지정해주었다 

미리 선언하지 않고 바로 style값을 지정하고 싶다면 다음과 같이 작성하자 

import React from 'react';


function App() {
  const name = '리액트';
  return (
    <div style={{
      backgroundColor: 'black',
      color: 'aqua',
      fontSize: '48px',
      fontWeight: 'bold',
      padding: 16
    }}>
      {name}
    </div>
  );
}

export default App;

 

 

class 대신 className

일반 HTML에서 CSS클래스를 사용할때는

<div class="myclass"></div>

와 같이 class라는 속성을 설정한다 

하지만 JSX에서는 class가 아닌 className으로 설정해주어야 한다 

우선 src디렉터리 안에있는 App.css를 열어 다 지우고 새로 작성하자 

.react {
  background: aqua;
  color: black;
  font-size: 48px;
  font-weight: bold;
  padding: 16px;
}

이번에는 기존 App컴포넌트에서 인라인 스타일에 사용한 폰트 색상과 배경색을 바꾼 스타일이다 

App.js파일에서 상단에 App.css를 불러온뒤 div요소에 className값을 지정하자 

import React from 'react';
import './App.css';

function App() {
  const name = '리액트';
  return <div className="react">{name}</div>
}

export default App;

JSX를 작성할때 CSS클래스를 설정하는 과정에서 className이 아닌 class값을 설정해도 스타일이 적용되기는 한다 

하지만 그렇게 사용하면 브라우저 개발자 도구의 Console탭에 다음과 같은 경고가 나타난다 

 

이전에는 class로 CSS클래스를 설정할때 오류가 발생하고 CSS클래스가 적용되지 않았는데, 리액트 v16이상부터는 class를 className으로 변환시켜주고 경고를 띄운다 

 

꼭 닫아야 하는 태그 

html 코드를 작성할때 가끔 태그를 닫지 않은 상태로 코드를 작성 하기도 한다 

예를들어 input html요소는

<input></input>

과 같이 입력하지 않고 

<input>

처럼 입력해도 작동한다

html에서 다음과 같은 코드는 문제 없이 동작한다

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form>
        성: <br>
        <input><br>
        이름: <br>
        <input>
    </form>
</body>
</html>

위 코드에서 br과 input 태그는 열기만 하고 닫지 않았다 

JSX에서는 위 코드처럼 태그를 닫지 않으면 오류가 발생한다 

다음과 같이 App.js파일의 코드를한번 수정해보자 

import React from 'react';
import './App.css';

function App() {
  const name = '리액트';
  return(
    <>
      <div className="react">{name}</div>
      <iput>
    </>
  );
}

export default App;

코드를 저장하면 다음과 같이 에러가 발생한다

이 오류를 해결하려면 input 태그를 닫아줘야 한다

import React from 'react';
import './App.css';

function App() {
  const name = '리액트';
  return(
    <>
      <div className="react">{name}</div>
      <input></input>
    </>
  );
}

export default App;

 

태그 사이에 별도의 내용이 들어가지 않는 경우 다음과 같이 작성할 수도 있다 

이러한 태그를 self-closing 태그라 부른다 

태그를 선언하면서 동시에 닫을수 있는 태그다 

import React from 'react';
import './App.css';

function App() {
  const name = '리액트';
  return(
    <>
      <div className="react">{name}</div>
      <input />
    </>
  );
}

export default App;

 

 

 

주석 

JSX안에서 주석을 작성하는 방법은 일반 자바스크립트에서 주석을 작성할 때와 조금 다르다 

import React from 'react';
import './App.css';

function App() {
  const name = '리액트';
  return(
    <>
      { /* 주석은 이렇게 작성한다. */ }

      <div className="react" //시작태그를 여러줄로 작성하게 된다면 여기에 주석을 작성할수도 있다 
      >
        {name}
      </div>
      // 하지만 이런 주석이나 
      /* 이런 주석은 페이지에 그대로 나타나게 된다. */
      <input />
    </>
  );
}

export default App;

 

JSX 내부에 주석을 작성할 때는

{ /*    */ }

와 같은 형식으로 작성한다 

이렇게 여러줄로 작성 할수도 있다 

그리고 시작 태그를 여러줄로 작성 할때는 그 내부에 //와 같은 형태로도 주석을 작성할수 있다 

만약 일반 자바스크립트에서 주석을 작성할때 처럼 아무데나 주석을 작성하면 그 주석은 페이지에 나타난다 

 

반응형