본문 바로가기
📌 Front End/└ React

[React] 리액트 JSX(TSX) 문법

by 쫄리_ 2024. 8. 17.
728x90
반응형

❓리액트(React)

리액트는 프론트엔드 개발을 위한 Javascript의 오픈소스 라이브러리이다. 
HTML, Javascript만으로도 충분히 웹을 만들 수 있는데 왜 리액트를 사용하는걸까?

JavaScript에서는 DOM 을 변형시키기 위하여

브라우저의 DOM Selector API를 사용해서 특정 DOM 을 선택한 뒤,

특정 이벤트가 발생하면 변화를 주도록 설정해야했다.

 

이를 이용하여 프로젝트를 진행했을 때 규모가 커질 수록 Dom Selector를 많이 쓰게 되고,

그러한 코드가 쌓여갈 수록 매우 지저분하다는 생각이 들었다.

사실 하나씩 불러오는 것도 매우 귀찮았다.

사용자와 인터랙션이 자주 발생하여 동적으로 UI를 구현해야 한다면

관리하기도 힘들고, 규모가 커질 수록 성능 저하의 원인이 될 수도 있는 문제가 발생 한다.

하지만, 리액트는 Virtual DOM을 이용하여 훨씬 간편하고 빠른 성능을 유지할 수 있도록 해준다. 

여기서 Virtual DOM은 브라우저에 실제로 보여지는 DOM이 아니라,

메모리에 가상으로 존재하는 것으로 Javascript 객체이기 때문에

실제로 브라우저에 DOM을 보여주는 것보다 훨씬 속도가 빠른 것이다. 

 

이러한 가상 돔을 이용하는 리액트는 상태가 업데이트 되면, 

업데이트가 필요한 곳의 UI를 Virtual DOM을 통해서 렌더링 되고, 

실제 브라우저에 보여지고 있는 DOM과 비교를 한 후, 실제 DOM에 패치시켜준다. 

 


📢 리액트 유용한 특징

  • 선언형 (JSX 문법)
  • 컴포넌트(Component) 기반
  • 범용성

 

 


🔎 선언형

개발에서 선언형이라는 뜻은

코드를 자세히 분석하지 않고도, 코드의 의도를 분명히 알 수 있게 작성하는 것을 의미한다.
리액트를 사용하지 않을 때에는 HTML, CSS, JS 파일을 넘나들며 코드를 작성했다. 

하지만 리액트는 이런 불필요한 과정을 함축시켜 하나의 파일에 모든 것을 작성할 수 있도록 

HTML + JS 문법인 JSX를 기반으로 직관적으로 코드를 작성할 수 있도록 하는 것이 특징이다.

코드만 봐도 오른쪽에 있는 웹 화면처럼 어떻게 구현이 될지 상상이 가능할 것이다. 

이것이 바로 리액트의 선언형 특징이다.

 


🔎 컴포넌트(Component) 기반

컴포넌트는 하나의 기능 구현을 위해 여러 종류의 코드를 묶어둔 것이다.
쉽게 말하면 동일한 기능을 하는 코드들을 크게 묶어서 분류해놓은 것이 바로 컴포넌트이다.

이렇게 컴포넌트로 분리하면 서로 독립적이고 재사용이 가능하기 때문에 
기능 자체에 집중하여 개발할 수 있고, 유지보수도 편하고 컴포넌트간 의존성이 낮기 때문에 
유닛 테스트하기에도 매우 편한 장점이 있다.

 

만일 어떠한 리액트로 작성된 코드를 봤을 때 어떤 화면이 그려질지 상상이 간다면

그 코드는 매우 선언적이고 컴포넌트 기반으로 잘 작성된 코드라고 할 수 있다.

 

장바구니 화면을 리액트로 구현한다고 했을 때, 컴포넌트는 위와 같이 작성할 수 있을 것이다.

 


🔎 범용성

리액트에서 범용성이라는 것은 Javascript "라이브러리" 이기 때문에

기존에 다른 Javascript 프레임워크로 제작된 웹어플리케이션에

리액트를 추가해서 개발할 수 있다는 것을 의미한다.

 

즉 리액트는 Javascript 프로젝트 어디서든 유연하게 적용될 수 있다는 것이다.
또한 리액트의 형제격인 React-Native를 배우면 앱 개발도 가능하기 때문에 

웹 뿐만이 아닌 앱까지도 제작이 가능하다.

 


🧐 JSX(TSX) 란?

JSX와 TSX는 React에서 HTML 코드를 JavaScript 코드처럼 쓸 수 있게 해주는 문법입니다.

TSX도 JSX 문법을 따릅니다.

 

JSX는 React에서 UI를 구성할 때 사용하는 문법으로 Jacascript를 확장한 문법이다.
하지만 브라우저가 바로 실행할 수 있는 Javascript 코드가 아니기 때문에 

브라우저가 이해할 수 있도록 변환해주는 중간 과정이 필요하다.

이 때 이용하는 것이 바로 "Babel"이다. 

이를 이용해서 JSX를 브라우저가 이해할 수 있는 Javascript로 컴파일하고, 그 후에 화면에 렌더링이 되는 것이다.

 


📍 JSX 사용이유

컴포넌트 하나를 개발하기 위해서

필요한 파일이 하나 줄고, 가독성을 훨씬 좋게 코드를 작성할 수 있는 방법이 있다고 하면,

모두가 사용하려 하지 않을까?

 

사실 JSX문법이 없이도 리액트를 요소를 만들 수 있지만 가독성은 떨어지며

리액트의 특징 중 하나인 선언형과 모순 관계를 이루기 때문에 아무도 사용하지 않는다.

이러한 JSX 문법을 이용하면 더욱 명시적으로 코드를 작성할 수 있고, 

Javascript 문법과 HTML 문법을 동시에 이용하기 때문에 기능과 구조를 한 눈에 확인할 수 있다.

 


📌 JSX (Javascript XML)

JavaScript 안에서 HTML 같은 코드를 작성할 수 있게 해주는 문법입니다.

주로 React에서 사용되고, .jsx 확장자로 저장됩니다.


📌 TSX (TypeScript with JSX)

Typescript 기반, React Component를 사용할 때, 

React에서 TS로 HTML을 사용할 수 있도록 해주는 파일

JSX를 TypeScript와 함께 사용할 때 쓰는 문법입니다. 

TypeScript의 타입 체크 기능을 이용하면서 JSX 코드를 작성할 수 있고, 파일 확장자는 .tsx입니다.

 


📣 리액트 3가지 대표적 특징

  • JSX 문법
  • 컴포넌트(Component)
  • Virtual DOM

✅ JSX 문법

🏷️ 표기법 요약

변수 : const myElement
함수 : function sayHello()
HTML 태그 스타일 속성 : <h1 style={{ backgroundColor: 'blue' }}>파란색</h1>
컴포넌트 : <BookList />, <TopNavbar />

🔎 소개

  • HTML을 마치 JS처럼 편리하게 사용하기 위한 리액트 JS 확장 문법
  • HTML 문법을 JavaScript 코드 내부에 쓴 것이다.
  • 빌드 시 Babel에 의해 자바스크립트로 변환된다.
  • React 17릴리즈 이전버전은 React를 import 하지 않으면 JSX를 이해하지 못함
import React from 'react';

 


✍️ JSX 규칙

1. 반드시 태그는 닫혀야 한다.

TSX는 XML 기반으로 HTML을 표기하기 때문에 문법이 정확해야한다. (HTML 속성은 대소문자 구분)

<div>, <p>, <span>, <a> 같이 짝이 있는 태그의 경우 반드시 닫는 태그가 존재해야 한다. 

<img/>, <input/>, <br/> 같은 단독 태그(self-closing tag)의 경우에는 반드시 태그를 닫아줘야 한다. 

const 컴포넌트 = () => {
  const handleOnClickded = () => {...};
  return (
    <div>안녕하세요</div>
    <span>안녕하세요</span>
    <h1>안녕하세요</h1>
    <button onClick={handleOnClickded}/>
    <button onClick={handleOnClickded}>안녕하세요</button>
    <img src="이미지주소" alt="대체텍스트"/>
    <input type="text" value="hello"></input>
  )
}

 


 

2. 하나의 엘리먼트 안에 모든 엘리먼트 포함

JSX에서 여러 엘리먼트를 작성하고자 하는 경우, 최상위에서 opening tag와 closing tag로 감싸주어야 한다.

React에서는 부모 요소로 감싸기 위해 <Fragment></Fragment> 혹은 <></> 사용

 

 


 

3. JSX 스타일링 - Class와 Style정의

 

📌 class 속성 지정

 

JSX에서는 class 대신 className을 사용한다.

문자열로 줄 수도 있고 중괄호를 사용하여 JS 값으로 줄 수도 있다.

일반적인 자바스크립트에서 div의 class 속성을 지정할 때는 

<div class="myClass"></div> 로 선언하기도 한다.
JSX 에서는 className 이라는 속성을 사용해 class 를 지정한다.

class가 아닌 className을 쓰는 이유는 리액트에서 class는 이미 지정되어 있는 예약어이기 때문이다.

function App() {
  const class = "title";

  return <h1 className={class}>Hello 권소현</h1>;
}

 

📌 CSS 인라인(inline) 방식 적용

 

JSX에서 style을 정의할 때

camelCase 형태의 style name을 사용해야 하며, css 속성 뒤에는 세미콜론 대신 쉼표를 사용한다.

- 객체 형식으로 적용

- 기존 CSS에서 하이픈이 들어갔던 방식은 카멜케이스(camelCase)로 표시

- CSS의 값은 '문자열'로 대입

   <div style="background-color:'yellow'"></div>

render(){
  const style = {
      display: "flex",
      justifyContent: "center",
      alignItems: "center",
      backgroundColor: "black",
      fontSize: "16px",
  };

  return(
      <div style={style}>test</div>
  );
}
// 별도의 객체를 선언하는 방법 말고 직접 지정해줘도 된다.
function MyComponent() {
  return (
    <div style={{ backgroundColor: 'red', fontSize: '20px' }}>
      This is my component
    </div>
  );
}

 

➕ CSS파일을 따로 작성하고 class에 적용하는 방법

 

📜 App.css

.App {
  background-color: powderblue;
  color:red;
  font-size:36px;
}

 

📜 app.js

className을 사용해 class속성 적용

import './App.css';

class App extends Component {
  render(){
    return (
      <div className="App">
       <p>hello</p>
      </div>
    );
  }
}

 

➕ 이벤트 리스너 인라인(inline) 방식 등록

 

태그를 작성할 때 on 뒤에 이벤트 명을 작성하는 방식으로 바로 이벤트 리스너를 부착할 수 있다.

const introduce = () => alert("Hello World");

function App() {
  return <h1 onClick={introduce}>Hello 권소현</h1>;
}

 


 

4. Javascript 표현식 사용 시, 중괄호{} 이용

JSX에서 JavaScript를 쓰고자 한다면, 꼭 중괄호{}를 이용해야 한다. 

만일 중괄호를 사용하지 않으면 일반 텍스트로 인식한다.


 

5.사용자 정의 컴포넌트는 대문자로 시작(PascalCase)

React 엘리먼트가 JSX로 작성되면 "대문자"로 시작해야 한다. 

소문자로 시작하게 되면 일반적인 HTML 엘리먼트로 인식을 하기 때문이다.  

이렇게 대문자로 작성된 JSX 컴포넌트를 따로 사용자 정의 컴포넌트라고 한다.

 

  • 대문자로 시작하는 JSX 태그 : <MyButton> 같은 사용자 정의 컴포넌트
  • 소문자로 시작하는 JSX 태그 : <div> , <span> 같은 내장 컴포넌트
// JSX는 React.createElement를 호출하는 코드로 컴파일된다. React가 스코프내에 존재해야한다.
import React from 'react';

// 사용자 정의 컴포넌트를 태그로 사용할 때는 해당 컴포넌트가 반드시 스코프내에 존재해야한다.
import MyButton from 'MyButton';

<MyButton color"blue">Click Me</MyButton>

 


 

6. return() 안에서는 제어문을 사용할 수 없다.

  • if문 / for문 사용 불가
  • 변수와 연산자만 사용 가능
  • if문 대체 : 논리 연산자 / 삼항 연산자
  • for문 대체 : 배열 객체의 map 메서드 사용

JSX로 조건부를 작성할 때는 Javascript 처럼 if 문이 아닌 삼항연산자로 작성해야한다.

 

 

📌 map 메서드 사용

map 메서드는 요소를 순회하며 값을 반환해 주기 때문에 사용이 가능합니다. 

map 순회 함수는 반드시 JSX를 반환해야 합니다. 반복문을 사용할 때에는 key값을 필수로 지정해주어야 합니다.

function App() {
  const weekArr = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"];

  return (
    <div>
      {weekArr.map((week, index) => (
        <span key={index}>
          {week}
        </span>
      ))}
    </div>
  );
}

 

 

📌 return 함수 호출

JSX 배열을 반환하는 함수를 미리 선언한 후 return 문에서 호출하는 것이 가능합니다. 

이렇게 하면 코드가 깔끔해지고 함수의 재사용이 가능합니다.

function App() {
  const weekArr = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"];
  
  const rendering = () => {
    const result = [];
    for (let i = 0; i < weekArr.length; i++) {
      result.push(<span key={i}>{weekArr[i] + " / "}</span>);
    }
    return result;
  };

  return <div>{rendering()}</div>;
}

 

조건부에 따라 다른 렌더링 시 

JSX 주변 코드에서 if문을 사용하거나, 

{}안에서 삼항 연산자(조건부 연산자)를 사용한다.

 

📌 외부에서 사용

function App() {
  let desc = '';
  const loginYn = 'Y';
  
  if(loginYn === 'Y') {
    desc = <div>권소현 입니다.</div>;
  } else {
    desc = <div>비회원 입니다.</div>;
  }
  
  return (
    <>
     {desc}
    </>
  );
}

 

📌 내부에서 사용

function App() {
  const loginYn = 'Y';
  
  return (
    <>
      <div>
         {loginYn === 'Y' ? (
            <div>권소현 입니다.</div>
         ) : (
            <div>비회원 입니다.</div>
         )}
      </div>
    </>
  );
}

 

📌 AND연산자(&&) 사용

// 조건이 만족하지 않을 경우 아무것도 노출되지 않는다.
function App() {
    const loginYn = 'Y';
    
    return (
        <>
          <div>
             {loginYn === 'Y' && <div>권소현 입니다.</div>}
          </div>
        </>
    );
}

 

📌 즉시실행함수 사용

function App() {
   const loginYn = 'Y';
   
   return (
       <>
          {
              (() => {
                 if(loginYn === "Y"){
                    return (<div>권소현 입니다.</div>);
                 }else{
                    return (<div>비회원 입니다.</div>);
                 }
              })()
          }
       </>
   );
}

 


 

7. 여러 개의 HTML 엘리먼트를 표시할 때, map() 함수 이용

React 에서 여러 개의 HTML 엘리먼트를 표시할 때는 "map()" 함수를 사용해야한다.
한 가지 중요한 점은 map 함수를 사용할 때는 반드시 "key" JSX 속성을 넣어야 한다는 것이다. 

key 속성을 넣지 않으면 화면 실행에는 문제가 없지만 리스트의 각 항목에 key를 넣어야 한다는 경고가 표시된다.

 

📝 map() 형태

map 메서드는 요소를 순회하며 값을 반환해 주기 때문에 사용이 가능합니다. 

map 순회 함수는 반드시 JSX를 반환해야 합니다. 반복문을 사용할 때에는 key값을 필수로 지정해주어야 합니다.

배열.map( (value, key) => 처리문 )

 

 

 

사용예시

 

📌 TSX 파일에서 작성된 TS Component 함수 return의 ()안에 HTML 태그를 포함할 수 있음

➡️ HTML 사용은 ()

➡️ TS 사용은 {}

  • return안에서 HTML을 표기하려면 ()로 묶여있어야 한다.
    return() 안에는 최상위 부모 태그가 무조건 1개만 있어야 한다. 
  • return() 안에서 TS를 사용하려면 {}로 묶어서 작성
    {}를 써서 TS를 작성할 땐 필수적으로 HTML 태그 안에 있어야 한다.
    return()안의 {}에서 다시 HTML을 표기할 때도 ()로 반환
import React, { Component } from 'react';

class App extends Component {
  // JSX에 <li>를 여러번 적지않기 위해 다음과 같이 처리한다.
  // 각 <li> tag는 고유한 key를 설정해줘야 한다.
  render() {
    let arr = ['호랑이', '코끼리', '독수리']
    let brr = arr.map((value, key) => <li key = {key}>{value}</li>);

    return (
      <div>
        <ul>
          {/* 리스트 생성 */}
          {brr}
        </ul>
      </div>
    );
  }
}

export default App;

 


JSX 내에서 주석 사용 방법

1. JSX 내에서 {/*…*/} 와 같은 형식을 사용 한다.

    return() 안에서는 HTML 주석 사용 불가

function App() {
  return (
      <>
        {/* 주석사용방법 */}
        <div>Hello, GodDaeHee!</div>
      </>
  );
}

 

2. 시작태그를 여러줄 작성 시에는, 내부에서 // 의 형식을 사용할 수 있다.

function App() {
   return (
      <>
          <div
          // 주석사용방법
          >Hello, GodDaeHee!</div>
      </>
   );
}

 


✅ 컴포넌트(Component)

🏷️ 요약

  • 컴포넌트끼리 데이터를 주고받을 땐 Props
  • 컴포넌트 내에서 데이터를 관리할 땐 State
  • 데이터는 부모 → 자식으로만 전달 가능하다.

 

🔎 소개

  • 컴포넌트는 UI의 조각이다. 컴포넌트를 활용하여 엘리먼트를 독립적으로 만들어줄 수 있다.
  • 엘리먼트의 재사용성을 높여준다.
  • 독립적, 재사용 가능한 코드의 조각이다.
  • 앱의 기능을 단위별로 캡슐화하는 React의 기본 단위
  • Component의 이름은 대문자로 시작
  • React는 소문자로 시작하는 컴포넌트를 DOM태그로 처리한다.
  • Class Component / Function Component로 나뉨

 


✍️ Element

  • 화면에 렌더링 할 DOM 노드들의 정보를 React에게 알려주기 위한 수단
  • type, props 필드를 가진다.
  • React.createElement() 혹은 JSX 로 작성한다.

 

✍️ Element 트리 종류

  • DOM Element : HTML tag를 가진 DOM 노드 <div></div>
  • Component Element : 사용자 정의 컴포넌트 <MyComponent />
    - 클래스형 컴포넌트
    - 함수형 컴포넌트

 


🏷️ 클래스형 / 함수형 컴포넌트 요약

현재는 함수형 컴포넌트(Function Component)가 주로 사용되고 있다.

리액트 함수형 컴포넌트 반드시 리액트 Element를 return해야 합니다.

// ▶ 클래스 컴포넌트
class Hello extends React.Component {
  render() {
    const { name } = this.props;
    return <div>{name}님 안녕하세요.</div>;
  }
}
 
// ▶ 함수 컴포넌트
const Hello = (props) => {
  const { name } = props.name;
  return <div>{name}님 안녕하세요.</div>;
};

🧱 클래스형 컴포넌트 (Class Component)

  • class 키워드가 반드시 필요하다.
  • Component로 상속 받아야 한다.
  • render() 메소드가 반드시 필요하다.
import React, { Component } from 'react';  

class App extends Component{ 	
   render() {     	
      return (         	
         // HTML이 들어갈 자리             
      ); 	
   } 
}

 

💡 클래스형 컴포넌트에서 Props 사용하기

클래스형 컴포넌트에서는 this.props를 통해 Props를 사용합니다.

// Welcome 클래스형 컴포넌트에서는 this.props를 통해 props를 사용합니다.
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

// 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때는 태그의 속성으로 값을 넘겨줍니다.
const element = <Welcome name="Alice" />;

 


🧱 함수형 컴포넌트 (Function Component)

  • 함수형 컴포넌트 선언이 매우 간편하다.
import React rom 'react';

function App() {
    return (  	
        // HTML이 들어갈 자리  
    );
}

 

💡 함수형 컴포넌트에서 Props 사용하기

함수형 컴포넌트에서 Props를 사용하려면 Props를 함수의 매개변수로 받아와서 사용하면 됩니다.

// Welcome 함수형 컴포넌트는 props를 매개변수로 받아와 사용합니다.
function Welcome(props) {
  return <h1>Hello, {props.name}!</h1>;
}

// 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때는 태그의 속성으로 값을 넘겨줍니다.
const element = <Welcome name="Alice" />;

 


📝 컴포넌트(Component)의 특징

  • 컴포넌트에 Attribute에 해당하는 부분을 Props(Properties)라고 한다.
  • 컴포넌트 안에 작성된 하위 Element를 children이라고 한다.
  • 그리고 children도 결국엔 props 중 하나이다.
<MyComponent user= {{name: "소현 color="blue"> {/* props */}
  <div>안녕~</div> {/* children */}
</MyComponent>

 

 

사용예시

상위 Element로부터 전달받은 props를 활용하는 코드이다.
이 컴포넌트의 자식(children) 요소 역시 props로부터 값을 받아오는 것을 볼 수 있다.

<MyComponent user= {{name: "소현 color="blue"> {/* props */}
  <div>안녕~</div> {/* children */}
</MyComponent>
const MyComponent = (props) => {
  const { user, color, children } = props
 
  return (
    <div style={{color}}>
      <p>{user.name}님의 하위 element는!</p>
      {children}
    </div>
  )
}

 


📝 Props 란?

  • Props는 컴포넌트에 값을 전달하는 역할을 수행한다.
  • 컴포넌트는 Props를 수정할 수 없는 순수 함수로 정의된다.
  • 순수 함수란 입력값이 바뀌지 않고 항상 동일한 입력값에 대해 동일한 출력 값을 제공하는 함수이다.
  • Props는 컴포넌트 호출 시, 인자 값의 이름과 내용을 함께 제공한다. 
    컴포넌트 내에서 props.[이름]의 형식으로 인자 값을 받아 사용한다.
function UserInfo(props){
  return(
    <div className="UserInfo">
      <div>영화: {props.name}</div>
      <div>한줄평: {props.text}</div>
    </div>
  )
}
 
const element = (
  <div>
    <UserInfo name="겨울왕국" text="엘사가 너무 예뻐요!" />
    <UserInfo name="신과함께" text="배우님 연기력 최고" />
  </div>
);

 


🧩 Props 사용법 

props를 사용해 전체 속성을 가져올 수도 있고

{중괄호 내부에 속성 이름을 지정해} 원하는 속성값만 사용할 수도 있다.

 

1. props로 전체 속성 가져오기

// ▶ Parent 컴포넌트 (실제 화면에 render되는 상위 component)
function Parent() {
  return (
    <Child title="WEB" sub="welcome to the world wide web" />
    // 1. 속성 지정
  );
};

// ▶ Child 컴포넌트
function Child(props) { // 2. props 가져오기

  console.log(props) 
  /* 
    props는 객체의 형태를 가진다. 
    {title: 'WEB', sub: 'welcome to the world wide web'}
  */
  
  return (
    <div>
      <h1>{props.title}</h1>
      <p>{props.sub}</p>
    </div>
    // 3. {} 안에 사용하려는 속성 작성
  );
};

 

 

2. 원하는 속성만 가져오는 방법 { … }

// ▶ Parent 컴포넌트 (실제 화면에 render되는 상위 component)
function Parent() {
  return (
    <Child title="WEB" sub="welcome to the world wide web" />
    // 1. 속성 지정
  );
};

// ▶ Child 컴포넌트
function Child({ title, sub }) { // 2. 원하는 속성만 가져오는 방법 {}

  console.log(title, sub) 
  // WEB, welcome to the world wide web
  
  return (
    <div>
      <h1>{title}</h1>
      <p>{sub}</p>
    </div>
    // 3. {} 안에 사용하려는 속성 작성
  );
};

 


🧩 props.children

{children} 은 컴포넌트가 여는 태그와 닫는 태그로 이루어져 있는 경우 태그의 value를 가져온다.
{props.children}를 사용하면 컴포넌트 자체를 props로 전달할 수도 있다.

 

사용예시

function Parent() {
  return (
    <Child title="sayHi">Hi, React!</Child> 
  );
};

function Child(props) {

  console.log(props) // {title: 'sayHi', children: 'Hi, React!'}

  return (
    <div>{props.children}</div> // Hi, React! 출력
  );
};

 

↑ 위 코드는 props로 전체 속성을 가져오고, 아래 코드는 ↓ {children}으로 컴포넌트의 value를 가져온다.
결과적으로는 두 코드는 같은 내용을 보여준다. (Hi, React! 출력)

function Parent() {
  return (
    <Child title="sayHi">Hi, React!</Child> 
  );
};

function Child({ children }) {

  console.log(children) // Hi, React!

  return (
    <div>{children}</div> // Hi, React! 출력
  );
};

 

 

사용예시

function Parent() {
  const apple = "🍎";
  const orange = "🍊";

  return (
    <Child>{apple}{orange}</Child> 
  );
};

function Child(props) {
  console.log(props.children) // ['🍎', '🍊']
  return (
    <div>{props.children}</div> 
  );
};

 


🧩 props로 동적으로 리스트 생성하기 (key)

list에 key를 입력해주지 않으면 리스트 각 항목에 key를 넣어야 한다는 경고가 표시된다.

(Warning: Each child in a list should have a unique "key" prop.)

key는 엘리먼트의 배열을 만들 때 포함해야 하는 

특별한 문자열으로 React가 어떤 항목을 변경, 추가 혹은 삭제할지 식별하는 것을 돕는다. 

엘리먼트들을 안정적으로 식별할 수 있도록 배열 내의 엘리먼트에 key를 제공해야 한다.

key는 같은 배열에 포함된 다른 요소 사이에서만 고유한 값을 가지면 된다. 

(전체 애플리케이션 또는 단일 컴포넌트 전체에서 고유값을 가질 필요는 없다.)

Math.random() 같은 값을 key로 사용하면 안된다.

React가 항목 추가, 제거 또는 다시 정렬할 시기를 결정할 수 있도록

key는 다시 렌더링하는 과정 동안 “안정적으로 식별 가능”해야 합니다.

이상적으로, Key는 id와 같이 데이터에서 사용되는 유일하고 안정적인 식별자를 사용하는 것이 좋다.

 

// ▶ App component (실제 화면에 render되는 component)
function App() {
  const topics = [
    { id:1, title:'html', body: 'html is...' },
    { id:2, title:'css', body: 'css is...' },
    { id:3, title:'js', body: 'js is...' },
  ]

  return (
      <Nav topics={topics}></Nav>
  )
}

// ▶ Nav component
function Nav(props) {
  console.log(props) // props로 App 컴포넌트의 topics 배열을 받는다. 

  /* → for문 사용
  const list = []
  for(let i=0; i<props.topics.length; i++) {
    let j = props.topics[i];
    list.push( <li key={j.id}><a href={`/${j.id}`}>{j.title}</a></li> )
  }
  */

  // → map사용
  const list = props.topics.map((value) => {
    return <li key={value.id}><a href={`/${value.id}`}>{value.title}</a></li>
  });

  return(
    <nav>
      <ol>
        {list}
      </ol>
    </nav>
  )
}

 


🧩 props 기본값 (default Props)

값이 지정되지 않았을 때, props에 기본값을 주길 원한다면

① 변수 바로 뒤에 =과 함께 기본값을 넣어 구조 분해 할당을 해주거나

② 컴포넌트에 defaultProps 값을 설정할 수 있다.

 

➡️ 기본값은 해당 prop이 없거나 {undefined}로 전달될 때 사용된다.
➡️ {null} 또는 {0}으로 전달된 경우는 기본값이 사용되지 않는다.

 

 

1. 변수 바로 뒤에 = 과 함께 기본값 넣기

function App() {
  return (
    <User name="fay" /> // age prop이 없는 User component
  )
}

function User({ name, age = 20 }) { // age 기본값 지정
  
  console.log(name, age) // fay, 20

  return (
    <div>
      <p>name: {name}</p>
      <p>age: {age}</p>
    </div>
  )
}

 

 

2. defaultProps 정의 

function App() {
  return (
    <div>
      <List list={undefined} /> 
      {/* list가 undefined인 경우 */}
    </div>
  )
}

const List = ({ list }) => {

  const items = list.map((items) => {
      return <li key={items.id}></li>
  });

  return (
    <div>
        <h2>리스트</h2>
        <div>
            <p>{list.length}개의 리스트가 있습니다.</p>
            <ul>
                {items}
            </ul>
        </div>
    </div>
  )
}

// List의 defaultProps
List.defaultProps =  {
    list: [],
};

 


📝 컴포넌트 구성하기

  • component는 다른 component를 조합하여 구성할 수 있다.
  • 부모 component에게 소속된 자식 component를 만들 수 있다.
  • 즉, 조합이 된 component ➡️ 자식 component
  • 조합을 한 component ➡️부모 component
function Welcome(props) {
  return <h1> Hello, {props.name}</h1>;
}
 
function App() {
  return (
    <div>
      <Welcome name="철수" />
      <Welcome name="민수" />
    </div>
  )
}
 
ReactDOM.render(
    <App />,
    document.getElementById("root")
);

 


📝 컴포넌트 합성

  • 컴포넌트는 다른 컴포넌트를 참조할 수 있다.
  • 컴포넌트 합성을 통해 코드의 재사용성이 향상된다.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
 
const Subject = (props) => {
    return <h3>React를 이해하기 위해서는 {props.name}을(를) 알아야 합니다.</h3>
}
 
const Curriculum  = () => {
    return (
        <>
            <Subject name="HTML" />
            <Subject name="CSS" />
            <Subject name="JavaScript" />
        </>
    )
}
 
ReactDOM.render(<Curriculum />, document.getElementById('root'));

 


📝 컴포넌트 추출하기

  • component를 추출하는 것은 여러 개의 작은 component로 나누는 것이다.
  • component는 핵심 component를 추출할수록 간단해진다.
  • React에서는 컴포넌트의 재사용을 위해 컴포넌트를 적절히 합성하고 추출하는 것이 좋다.

 


✍️ JSX.Element 타입

 

🔎 정의

JSX.ElementTypeScript가 JSX를 사용할 때 정의하는 타입입니다.

이는 기본적으로 ReactElement와 동일하지만, JSX 문법을 사용하는 경우에 한해 적용됩니다.

 

✏️ 사용

주로 JSX 문법을 사용하는 함수나 컴포넌트의 반환 타입으로 사용됩니다.

 


📌 JSX를 변수에 담을 때

 

박스라는 변수에 JSX.Element라는 타입을 선언해준다. 

그러면 JSX.Element에 해당하는 태그들을 사용하도록 제한하겠다는 것이다. 

이제 이 변수에 다른 타입은 올 수 없다. 

let 박스 :JSX.Element = <div></div>
let 버튼 :JSX.Element = <button></button>

let div:JSX.Element = <div>Hello</div>
root.render(
    <h1>{div}</h1>
);

 

intrinsicElement라는 타입이 있다. 

html태그의 종류는 한 100여 가지 정도되는데, 그것들을 모아놓은 타입이다.

저렇게 괄호를 열어서 해당 태그를 타입으로 지정할 수 있다.

기본태그들 사용할 때, 인트린식 엘리먼트를 사용한다고 생각하면 된다. 

let 박스 :JSX.IntrinsicElements['div'] = React.createElement('div');
let 버튼 :JSX.IntrinsicElements['button'] = <button></button>;

 

 

사용예시

📌 JSX.Element[] : JSX 요소로 이루어진 배열

import React from 'react';
import ReactDOM from 'react-dom/client';

const root = ReactDOM.createRoot(document.querySelector("#reactRoot") as HTMLElement);

let divs: JSX.Element[] = [
    <div>Hello1</div>,
    <div>Hello2</div>
];

root.render(
    <>{divs}</>
);

 

📌 컴포넌트(Component) 타입 지정 시

 

1. 컴포넌트를 담은 함수

컴포넌트는 항상 JSX를 return하기 때문에 JSX.Element로 타입을 지정하면 된다.

함수형 컴포넌트의 타입지정은 파라미터와 return 부분을 타입지정한다.

const App (): JSX.Element {
	return (
    	...
    )
}

 

 

2-1. props 타입 지정 (props는 속성을 나타내는 데이터)

 

📜 App.tsx 파일

const App(): JSX.Element {
  return (
    <div className="App">
      <Header menu={ menu } contact={ contact }/>
    </div>
  )
}

 

📜 Header.tsx 파일

const Header (props: { menu: string, contact: number }): JSX.Element {
  return (
    <div className="header">
      {props.menu}
      {props.contact}
    </div>
  )
}

 

 

2-2. 컴포넌트 바깥에 type 묶음을 만들어 사용


여기서 파라미터는 props를 말한다.

➡️ AppProps 라는 객체 형태의 타입을 지정한다. name 이라는 string 속성을 포함한다.
그리고 반환 타입으로는 <div>를 반환하기 때문에 JSX.Element 를 반환 타입으로 지정해주었다.
(하지만 컴포넌트는 JSX.Element를 return 하기 때문에 생략해도 자동으로 타입지정이 된다.)

type AppProps = {
  name: string;
}; 
 
function App(props: AppProps) :JSX.Element {
  return (
    <div>{message}</div>
  )
}
type Props묶음 = {
  menu: string,
  contact: number
}

const Header (props: Props묶음): JSX.Element {
  return (
    <div className="header">
      {props.menu}
      {props.contact}
    </div>
  )
}

 


✅ Virtual DOM

🔎 소개

  • React에서 제공하는 가상의 DOM
  • 가상의 DOM에서 변경된 내용만 먼저 확인해서 실제 DOM에 업데이트 하여 불필요한 단계를 줄인다.

 

✍️ DOM vs Virtual DOM

  • 기존 DOM : 조그만 변화가 일어나면 모든 DOM을 리렌더링하여 성능의 저하를 발생
  • Virtual DOM : 변화가 일어난 부분만(+자식컴포넌트들 까지)을 대체함
    DOM만을 사용할 때 보다 대부분의 렌더링 성능에서 우수함
    ※ DOM : 브라우저가 화면을 그리기위한 정보를 담고있는 문서 객체

728x90
반응형