코딩하는라민

[React] JSX 이해하기 본문

Core/React

[React] JSX 이해하기

코딩하는라민 2023. 2. 22. 00:45
728x90
반응형

[React] JSX 이해하기

 

📌 사용자 정의 컴포넌트

✅ Import

상단에 다른 곳에 정의된 코드를 불러와 현재 문서에서도 사용할 수 있게 해준다.

 

  • 리액트 라이브러리 불러오기
import React from 'react';

JSX 를 사용하기 위해서는 React 라이브러리를 파일로 불러와야한다.

단, cdn 으로 스크립트 태그를 넣었다면 React 는 전역변수이기 때문에 별도로 불러올 필요가 없다.

  • CSS 파일 불러오기
import './style.css';
  • 이미지 불러오기
import logo from './logo.svg';

 

✅ 렌더링

// HTML 파일
<div id="root"></div>

이 안에 들어가는 모든 요소를 ReactDOM에서 관리한다.

React 에서는 일반적으로 하나의 루트 DOM 노드가 있다.

 

 

렌더링하기 위해서는 DOM 요소를 ReactDOM.createRoot()에 전달해야 한다.

그 후 React 요소를 root.render 에 전달해야한다.

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

HTML 문서 body 아래의 요소 중 id가 root 인 DOM 요소를 선택해서 App 컴포넌트를 렌더링한다.

App 에는 렌더링되기 원하는 컴포넌트를 넣어주면 된다.

 

✅ 사용자 정의 컴포넌트는 대문자로 시작한다.

import React form 'react';

function Home(props){
    return <div>Go Home</div>
}

function Cafe(){
    return <Home />
}

소문자로 시작하는 경우 내장 컴포넌트를 의미하며, 이는 HTML 태그로 인식된다.

대문자로 시작하는 타입은 JS 파일 내 사용자가 정의했거나 import 한 컴포넌트를 가리킨다.

 

만약 컴포넌트의 이름을 소문자로 시작해야한다면?

→ 대문자로 시작하는 변수에 할당 후 사용하기

 

✅ 하나의 태그로만 감쌀 수 있으며, 자식 요소만 가질 수 있다.

function User(){
    return (
        <div>
            <h1>Hello</h1>
        </div>
    )
 }

만약 return 의 최 상위 요소가 여러개라면 다음과 같은 오류가 뜬다.

JSX 표현식은 한개의 부모 요소만 가진다.

 

또한,

태그는 반드시 닫아줘야한다.

만약 자식 컴포넌트가 없다면 자기 자신을 닫는 형태를 사용한다.

function User(){
    return <Header />
 }

 

✅ Export

컴포넌트 파일을 분리하는 경우 최하단에 해당 컴포넌트를 내보내줘야한다.

내보낸 컴포넌트를 사용하려면 사용하려는 파일 안에서 import 해준다.

export default App

이제 App 컴포넌트를 다른 모듈에서 사용할 수 있게 되는 것!

 

✅ Fragments

function Hello() {
    return (
      <div>
        <h1>Hello Dev</h1>
        <button>Good</button>
      </div>
    );
}

컴포넌트가 여러개의 요소를 반환하는 경우가 있다.

Fragments 는 DOM 에 별도의 부모 노드를 추가하지 않고도 여러 자식을 그룹으로 묶어줄 수있다.

function Hello() {
    return (
      <>
        <h1>Hello Dev</h1>
        <button>Good</button>
      </>
    );
}

 

⛔ 콘솔창에 두번씩 출력되는 문제
컴포넌트를 사용하면서 콘솔창에 두번씩 출력되는 것을 볼 수 있다.
이는 html 의 root 에 렌더할 때 컴포넌트를 StrictMode 라는 태그로 감싸줬기 때문이다.
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);​

엄격모드에서는 콘솔에 두 번씩 출력된다.
이 문제를 해결하기 위해서는 StrictMode 대신 빈 태그를 넣어주면 된다.
root.render(
  <>
    <App />
  </>
);​

 

📌 Props

prop 은 React 컴포넌트에 전달되는 모든 데이터를 뜻한다.

또한 props 는 HTML 에서의 속성(attribute)을 말한다.

리액트에서는 props 를 사용한다.

 

이 props를 이용하면 컴포넌트별로 다르게 렌더링할 수 있다.

function First(props){
    return(
        <header>
            {props.title}
        </header>
    )
}

function App(){
    return (
        <div>
            <First title="Hello" />
            <First title="Hi~" />
        </div>
    )
}

 

✅ JSX 안의 변수들

<img src={logo} className="App-logo" alt="logo" />

img태그 안의 src 속성의 속성값은 중괄호 안에 들어가있는데, 이것이 JSX 가 변수를 인식하는 방법이다.

 

✅ default value

props 의 기본값은 true 이다.

<Home sleep />

<Home sleep={true} />

이렇게 prop 값을 전달하지 않을 경우 자바스크립트의 객체의 단축 표기법과 헷갈릴 수 있기 때문에 권장하지 않는다.

// 단축 표기법
const Home {
    sleep
}

// 위와 동일
const Home {
    sleep: sleep
}

 

✅ 자바스크립트 표현식 사용

자바스크립트의 표현식을 { } 싱글 컬리브레이션을 통해 JSX 안에 prop 으로 사용할 수 있다.

<Header count={ 2 * 2 } />

 

JSX 안에서는 '문'을 사용할 수 없다.

하지만, JSX 밖에서는 사용할 수 있다.

 

✅ className

JSX 에서는 class 라는 단어를 사용할 수 없고, className 이라는 이름으로 사용한다.

className 은 HTML 의 class 와 같다.

<Header className="header" />

 

✅ 전개 연산자로 props 넘겨주기

전개 연산자로 객체 형태의 props 값을 그대로 넘겨줄 수 있다.

function one(){
    return <Header title="Hello React" className="header" />
}
function two(){
    const props = { title: 'Hello React', className: 'header' }
    return <Header {...props} />
}

 

특정 prop 은 선택하고, 나머지 prop 은 전개 연산자로 넘기기

function Header(props) {
  const { title, ...other } = props;
  const className = title === "react" ? "JSX" : "create-react-app";
  return <button className={className} {...other} />;
};

function App() {
  return (
    <>
      <Header title="react" onClick={() => console.log("funny!")} sub="welcme!" >
        Hello, react World!
      </Header>
    </>
  );
};

 

const { title, ...other } = props;

해당 함수 내에서는 title 이라는 변수는 선언되어있지 않았기 때문에 const로 변수를 선언해준다.

그리고 이렇게 선언해준 객체에 props 객체를 할당해주면 App 컴포넌트에서 사용한 props 를 하위 컴포넌트인 Header 에서 변수로 사용할 수 있는 것이다.

 

여기서 other 는 title prop 을 제외한 onClick, sub 가 된다.

 

✅ props 는 읽기 전용

리액트에서 데이터의 흐름은 `단방향`이다.

즉, props 는 부모 컴포넌트에서 자식 컴포넌트로 내려간다.

 

📌 JSX 에서 자식 다루기

✅ 자식요소 : 문자 리터럴

<Coffee>chocolate milk</Coffee>

Coffee의 props.children 은 "chocolate milk" 가 된다.

 

✅ 자식요소 : JSX

중첩된 컴포넌트

<Home>
    <Sleep />
    <Sleep />
    <Sleep />
</Home>

문자열 리터럴 자식과 JSX 자식을 함께 사용할 수 있다.

 

✅ 자식요소 : JS 표현식

자식 요소로 JS 표현식을 사용할 수 있다.

또한 JSX 표현식의 배열을 렌더링할 수도 있다.

function Home(props) {
  return <li>{props.todo}</li>;
}

function Today() {
  const today = ['sleep', 'eat', 'game'];
  return (
    <ul>
      {today.map((arr) => <Home todo={arr} next={arr} />)}
    </ul>
  );
}

=

<ul>
    <li>sleep</li>
    <li>eat</li>
    <li>study</li>
</ul>

 

요소자식 : 함수

function Coffee(props){
    let arr=[];
    for(let i=0; i<props.count; i++){
        arr.push(props.children(i));
    }
    return <section>{arr}</section>
}

function Cafe(){
    return(
        <Coffee count={5}>
        	{ (num) => <div number={num}>This is {num}</div> }
        </Coffee>
    )
}

위와 같이 상위 컴포넌트에 children 에 함수를 집어넣고, 하위 컴포넌트에 빈 배열에 상위 cnildren 요소를 하나씩 push 해 자식 요소를 추가해줄 수도 있다.

 

✅ true, false, null, undefined

true, false, null, undefined 는 유효한 자식이지만, 렌더링되지 않는다.

따라서 아래의 JSX 표현식들은 전부 같게 렌더링된다.

<div />
<div>{true}</div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>

이 값들을 문자열로 출력하고 싶다면, {String( )} 으로 감싸서 출력해주면 된다.

 

✅ 조건부 렌더링

<div>
    {milk && <Coffee />}
</div>

milk 가 true 일 경우 <Coffee /> 를 반환하게 된다.

만약 milk 가 false 라며 milk 를 반환.

 

만약 앞의 값이 빈배열의 길이라고 한다면, 0을 렌더링한다.

0으 다른 boolean 값과 다르게 렌더링이 되기 때문이다.

따라서 연산자 && 앞의 표현식은 언제나 boolean 값이 나오도록 조건처리 해줘야한다.

<div>
    {milk.length > 1 && <Coffee />}
</div>

 

 

 


참고 : MDN 문서, 리액트 공식 문서
  등을 공부하고, 간단하게 정리한 내용입니다. 잘못된 부분이나 문제되는 점이 있으면 댓글 부탁드립니다.

728x90
반응형