[React] React 완벽 가이드 - React 핵심 - 컴포넌트, JSX, 속성, 상태 등




개요

실습 내용

  • Component로 User Interface 만들기
  • 값 다루기
  • Event 다루기
  • 상태로 상호작용하는 UI 만들기


학습 목표

  • 근본적인 리액트 개념 이해하기
  • 정적인 기본 리액트 앱과 동적인 상호작용을 포함한 앱 실습




Component

  • section/block을 나눠서 UI를 구성하는건 리액트에서만이 아닌 흔한 개념이다.
  • 비슷한 소스를 같이 놓을 수 있다
    • 자바스크립트, html 코드가 함께 있기 때문에, 수정 시에 여러 개의 파일을 수정하지 않아도 됨
  • React Component - HTML, CSS, JavaScript 가 포함됨
  • 각 컴포넌트에 다른 기능이 있어서, 기능별로 분리해서 관리하기 좋다.




실습 프로젝트 세팅

$ npm start 
$ npm run
  • start는 한번만 하면 됨




JSX와 리액트 컴포넌트 [핵심 개념]

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>React Essentials</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/index.jsx"></script>
  </body>
</html>
  • 렌더링/빌드 이런건 리액트에서 해준다.
  • 코드가 간단하고 <script type="module" src="/src/index.jsx"></script> 이 부분을 보면, js파일을 로딩할 수 있는 것처럼 보임



JSX

function App() {
  return (
    <div>
      <header>
        <img src="src/assets/react-core-concepts.png" alt="Stylized atom" />
        <h1>React Essentials</h1>
        <p>
          Fundamental React concepts you will need for almost any app you are
          going to build!
        </p>
      </header>
      <main>
        <h2>Time to get started!</h2>
      </main>
    </div>
  );
}

export default App;
  • 해당 파일을 보면 HTML과 js코드가 섞여있음 => JSX 특징
  • 브라우저에는 사용이 불가능함을 주의
    • 리액트에서는 브라우저에 도달하기 전에 리액트에서 빌드함


JSX로 컴포넌트 개발 시 지켜야하는 것

  • 함수가 대문자로 시작해야함
  • 함수에서 렌더링 가능한 값이 반환되어야함
    • 대체로 HTML 마크업이 반환됨


컴포넌트 만들어보기

function Header() {
  return (
    <header>
      <img src="src/assets/react-core-concepts.png" alt="Stylized atom" />
      <h1>React Essentials</h1>
      <p>
        Fundamental React concepts you will need for almost any app you are
        going to build!
      </p>
    </header>
  );
}

function App() {
  return (
    <div>
      <Header></Header>
      <main>
        <h2>Time to get started!</h2>
      </main>
    </div>
  );
}
  • 이렇게 기존에 App() 에 있던 Header를 컴포넌트로 분리하고 App()에서는 <Header></Header> 또는 <Header />로 가져올 수 있다.




리액트의 컴포넌트 처리 과정

import ReactDOM from "react-dom/client";

import App from "./App.jsx";
import "./index.css";

const entryPoint = document.getElementById("root");
ReactDOM.createRoot(entryPoint).render(<App />);
  • render 호출

동적으로 값 로딩

import reactImg from './assets/react-core-concepts.png';


const reactDescriptions = ['Fundamental', 'Crucial', 'Core'];

function genRandomInt(max) {
  return Math.floor(Math.random() * (max + 1));
}

function Header() {
  
  const description = reactDescriptions[genRandomInt(2)];

  return (
    <header>
      <img src={reactImg} alt="Stylized atom" />
      <h1>React Essentials</h1>
      <p>
        {description} Fundamental React concepts you will need for almost any app you are going to build!
      </p>
    </header>
  );
}
...
  • {}안에 값을 넣어서 이미지를 가져오거나, 함수를 호출할 수 있음.

Prop(속성)으로 컴포넌트 재사용

  • Component도 함수로 정의하여 쉽게 생성할 수 있음
  • props를 사용해서 컴포넌트 속성을 만들때 넣어줄 수 있음

컴포넌트 Export

위에서 Header를 별도의 파일로 써볼거임

import reactImg from '../assets/react-core-concepts.png';

const reactDescriptions = ['Fundamental', 'Crucial', 'Core'];

function genRandomInt(max) {
  return Math.floor(Math.random() * (max + 1));
}

export default function Header() {
  
    const description = reactDescriptions[genRandomInt(2)];
  
    return (
      <header>
        <img src={reactImg} alt="Stylized atom" />
        <h1>React Essentials</h1>
        <p>
          {description} Fundamental React concepts you will need for almost any app you are going to build!
        </p>
      </header>
    );
}
  • 이렇게 export default 를 붙여서 별도의 파일로 만든다.


import Header from './components/Header.jsx';
  • 기존에 소스가 있던 App.jsx 에 import 시켜주면 됨





컴포넌트 css 스타일 지정하기

  1. 기존에 index.css 에 있는 header 관련 css 코드 잘라내기
  2. Header.jsx 파일 있는 경로에 Header.css 생성 후 붙여넣기
  3. Header.jsx 파일 상단에 import './Header.css'; 가져오기


이렇게 컴포넌트에 css를 따로 배정하면 좋은 점

  • 컴포넌트 별로 스타일을 다르게 적용할 수 있음
    • header 라는 태그에 대한 css를 해당 컴포넌트에 한정해 적용시킬 수 있다.





컴포넌트 - props.children

  • prop중에 기본으로 무조건 갖고있는 속성이 있음 그게 children
  • 쓰는 목적 : <> 태그 사이에 있는 내용을 전달하고 사용함
export default function TabButton({children}) {
    return <li><button>{children}</button></li>
}
            <TabButton>Components</TabButton>
  • 이렇게 TabButton 태그 안에 있는 텍스트가 children property로 들어감



export default function TabButton(label) {
    return <li><button>{label}</button></li>
}
            <TabButton label="Components"></TabButton>
  • 이렇게 쓰는 방법도 있음





이벤트 처리하기

  • 이렇게 element에 on~~ 하는식으로 이벤트 쓸 수 있는게 많음~


export default function TabButton({children}) {
    
  function handleClick() {
    console.log('Hello World!');

  }

  return (
          <li>
            <button onClick={handleClick}>{children}</button>
          </li>
  );
}
  • button에 onClick이벤트를 prop으로 넣어주고, function 추가해주면 됨
    • 여기서 handle로 시작하고 이벤트이름(Click)을 붙여주는게 약간 관행?
  • 주의할 점 : handleClick() 으로 쓰면 안됨!
    • 차이는 괄호가 없으면 리액트에서 언젠간 실행하는거고, 괄호를 쓰면 함수가 바로 실행됨
    • 화면 랜더링 전에 함수가 실행되어버리면 안되니까, 괄호를 없애도록~



export default function TabButton({children, onSelect}) {
    return (
        <li>
            <button onClick={onSelect}>{children}</button>
        </li>
    );
}

function App() {

  function handleSelect() {
    console.log('Hello World - selected!');
  }
  ...
  <menu>
    <TabButton onSelect={handleSelect}>Components</TabButton>
    ...
  • 파라미터로 넣어줄 수도 있음
  • App쪽에 () => handleSelect() 이렇게 익명함수 넣어주게 되면?
    • onSelect에 값으로 실행됨,onClick도 값으로 실행됨
    • 이제 그러면 동작은 값만 적어준거랑 같지만, () => handleSelect('components') 같이 인자 값도 넣어줄 수 있게 되는거임





State

UI 업데이트

  • 변화를 탐지할때 UI를 업데이트함
  • 각 파일에 대해 태그 찍힌부분을 딱 실행할 때 한번 랜더링하는거임
  • state 를 통해서 이 UI를 업데이트 할지말지를 관리할거임



State 관리 & Hooks 사용법

import { useState } from 'react';

function App() {

  const [ selectedTopic, setSelectedTopic ] = useState('Please click a button');

  function handleSelect(selectedButton) {
    setSelectedTopic(selectedButton);
    console.log(selectedTopic);
  }


  return (
          ...
          {selectedTopic}
          ...
  );
            
}

  • 컴포넌트 함수의 최상위에서 useState() 호출해야함
    • Hook의 중요한 규칙~!
  • 0으로 쓴건 selectedTopic 들어가고, setSelectedTopic 함수임. (이 함수는 react에서 제공)

다른 글