[React] 기본 개념 정리
해당 글은 React 공식 문서(https://ko.react.dev/learn)를 보면서 공부하며 정리한 내용입니다.
리액트를 처음 공부했을 때 헷갈렸던 개념들을 중심으로 적어두었습니다.
1. React 컴포넌트의 이름은 항상 대문자로 시작해야 한다.
컴포넌트 이름이 대문자로 시작하지 않으면 HTML 태그로 간주한다.
home 이라는 컴포넌트가 있을 때, <home /> 형태로 렌더링할 경우 DOM 요소로 처리되어 의도한 대로 동작하지 않을 수 있다!
※ 클래스나 함수 선언 시, 선언부 앞에 export를 붙인다고 해서 함수 선언문에서 함수 표현식으로 바뀌지 않기 때문에 함수나 클래스 선언 끝에는 세미콜론을 붙이지 말라고 권유 함.
※ export default 라 문법을 사용하면 '해당 모듈엔 개체가 하나만 있다' 라고 명확하게 나타낼 수 있다.
※ named export 의 경우 내보냈을 때 사용한 이름 그대로 가져와야하지만, default export는 가져올 때 원하는 이름을 지정해 줄 수 있다.
2. JSX와 중괄호
JSX는 JavaScript 표현식을 HTML문법으로 작성할 수 있게 도와주는 문법이다.
중괄호 { } 는 JSX 내에서 JS 표현식을 삽입하는 역할을 한다.
아래와 같은 방식으로 데이터를 삽입할 수 있으며,
연산식, 함수호출, 조건문 등의 표현식도 중괄호 안에 포함시킬 수 있다!
return (
<h1>
{user.name}
</h1>
);
3. 조건부 렌더링
조건에 따라 다른 컴포넌트를 렌더링하고자 할 때는 if 문이나 삼항 연산자를 사용할 수 있다.
if문
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
삼항 연산자
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
※ 조건부 삼항 연산자?
세 개의 피연사자를 받는 유일한 연산자로 앞에서부터 조건문, 물음표(?), 조건문이 참일 경우 실행할 표현식, 콜론(:), 조건문이 거짓일 경우 실행할 표현식이 정의된다.
condition ? exprIfTrue : exprIfFalse;
4. useState로 상태 관리하기
컴포넌트가 화면에 표시되는 정보에 따라 동작을 다르게 해야할 경우 useState를 사용하여 상태를 관리할 수 있다.
ex) 버튼이 클릭된 횟수를 세고 싶을 때
import { useState } from 'react';
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
버튼이 처음 표시될 때 useState()에 0을 전달했기 때문에 count가 0이 된다.
State를 변경하고 싶다면 setCount()를 실행하고 새 값을 전달하고, 이 버튼을 클릭하면 카운터가 증가한다.
컴포넌트를 여러 번 렌더링할 때의 상태분리
import { useState } from 'react';
export default function MyApp() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
같은 컴포넌트를 여러 번 렌더링하더라도, 각 인스턴스는 독립적인 상태를 가진다.
각 버튼은 개별적으로 클릭 횟수가 늘어나며, 서로의 상태에 영향을 주지 않는다!
리액트가 컴포넌트를 고유한 인스턴스로 처리하기 때문이다.
5. 상태 공유와 Props 전달
두 개의 버튼이 동일한 count 상태를 공유하도록 구성하고 싶을 경우, 상태를 상위 컴포넌트에서 관리하고 하위 컴포넌트로 props를 통해 전달해야 한다!
import { useState } from 'react';
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
먼저 MyButton에 정의되었던 State를 MyApp으로 이동시키고,
그 다음 공유된 클릭 핸들러와 함께 MyApp에서 각 MyButton으로 State를 전달한다.
중괄호를 통해 전달한 정보를 Props라고 한다.
이제 MyApp 컴포넌트는 count State와 handleClick 이벤트 핸들러를 포함하며, 이 두가지를 각 버튼에 Props로 전달한다.
마지막으로, 부모 컴포넌트에서 전달한 Props를 읽도록 MyButton을 변겅한다.
" 컴포넌트 간 State를 공유하는 과정 "
1. 버튼을 클릭하면 onClick 핸들러 실행
2. onClick Prop은 MyApp 내부의 handleClick 함수 실행
3. handleClick 함수는 setCount(count + 1)을 실행하여 count State 변수를 증가시킴
4. 새로운 count 값은 각 버튼에 Prop으로 전달
5. 모든 버튼에는 새로운 값 표시
6. Hook 사용 시 주의사항
useState, useEffect와 같은 Hook은 컴포넌트 함수의 최상단에서만 호출해야 한다. 조건문, 반복문의 내부에서는 호출할 수 없다.
// 올바른 사용
function Component() {
const [state, setState] = useState(0);
}
// 잘못된 사용
function Component() {
if (condition) {
const [state, setState] = useState(0); // 오류 발생 가능
}
}
※ Hook은 컴포넌트 렌더링 순서에 의존하여 작동하기 때문에 호출 순서가 바뀌면 문제가 발생할 수 있다.
초기 학습 시 가장 많이 혼동되는 부분들에 집중하여 예제를 중심으로 구성하였으며, 향후 useEffect, useRef, 이벤트 처리 방식 등 보다 심화된 개념도 정리할 예정이다.