[React] React 완벽 가이드 - React 핵심 - 컴포넌트, JSX, 속성, 상태 등
2024, Oct 30
목차
개요
실습 내용
- 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 스타일 지정하기
- 기존에
index.css
에 있는 header 관련 css 코드 잘라내기 Header.jsx
파일 있는 경로에Header.css
생성 후 붙여넣기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에서 제공)