React 앱은 컴포넌트로 구성된다.
컴포넌트는 마크업을 반환하는 자바스크립트 함수로 작성한다.
- 컴포넌트 명명은 대문자로 시작한다. ex) MyButton
- JSX 문법이므로, <br/> 처럼 태그를 닫아줘야 한다.
- 여러 개의 JSX 태그를 반환할 수 없으므로 <div> ... </div> 와 같이 부모로 감싸주어야 한다.
- html문법을 jsx로 변환해주는 사이트: https://transform.tools/html-to-jsx
function MyButton() {
return (
<button>I'm a button</button>
);
}
//컴포넌트 생성
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
//다른 컴포넌트 안에 중첩
스타일 추가하기
React에서는 class가 아닌 className으로 CSS 클래스를 지정한다.
<img className="avatar" />
/* In your CSS */
.avatar {
border-radius: 50%;
}
데이터 표시하기
중괄호를 사용하여 태그안에 일부 변수를 삽입하거나 어트리뷰트 값을 설정할 수 있다.
*주의 : 스타일 값이 자바스크립트 변수에 의존할때는 {} 객체로 전달해야 된다.
//인라인 스타일은 이렇게 작성해요
<div style={{ color: userColor }}>
// 첫 번째 중괄호 {} : JSX에서 자바스크립트를 쓰기 위한 것
// 두 번째 중괄호 {} : 자바스크립트 객체를 나타내는 것
const user = {
name: 'Hedy Lamarr',
imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
imageSize: 90,
};
export default function Profile() {
return (
<>
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'Photo of ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize
}}
/>
</>
);
}
조건부 렌더링
if문을 사용하여 나태낼 수 있지만 더 간결하게 표현하기 위해 삼항 연산자를 주로 사용한다.
//if문 사용
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
//삼항연산자
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
else 분기가 필요하지 않다면 && 연산자로 나타낼 수 있다.
<div>
{isLoggedIn && <AdminPanel />}
</div>
리스트 렌더링하기
리스트 같이 반복되는 컴포넌트를 보여주기 위해서는 for문이나 map() 을 이용한다.
//다음과 같은 데이터가 있다고 가정
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];
//해당 제품 배열을 <li> 항목 배열로 반환
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
중요!! 반복되는 컴포넌트를 반환할때는 key를 설정하자. React가 목록이 변경될 때 어떤 항목이 바뀌었는지 빠르게 찾을 수 있어 성능 최적화에 도움이 된다. (key는 겹치지 않는 고유한 값으로 해야 된다.)
이벤트에 응답하기
컴포넌트 내부에 이벤트 핸들러 함수를 선언하여 이벤트에 응답할 수 있다.
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
//이벤트 선언
<button onClick={handleClick}>
Click me
</button>
);
}
중요한 점:
- onClick={handleClick} (O)
- onClick={handleClick()} (X)
왜냐하면:
- handleClick: "이 함수를 나중에 클릭할 때 실행해줘"
- handleClick(): "이 함수를 지금 당장 실행해!"
쉽게 말해서, React한테 "버튼 클릭하면 이 함수 실행해줘"라고 함수를 건네주는 것!
화면 업데이트하기
버튼을 클릭했을때 클릭된 수 만큼 변하는 값을 화면에 표시해주고 싶다면? 컴포넌트에 state를 추가한다.
import { useState } from 'react';
useState로부터 현재 state (count)와 이를 업데이트할 수 있는 함수(setCount)를 얻을 수 있다.
const [값, 값을바꾸는함수] = useState(초기값);
어떤 이름으로도 지정할 수 있지만 [something, setSomething]으로 작성하는 것이 일반적이다.
useState의 특징은 다음과 같다.
- 컴포넌트가 리렌더링되어도 값이 유지됨
- 값이 변경되면 화면이 자동으로 업데이트됨
- 여러 개의 상태를 동시에 관리할 수 있음(단, 너무 많이 관리할 경우 코드가 복잡해질 수 있음)
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
count 값은 초기값을 0으로 설정했기에 처음에는 0으로 뜬다.
버튼을 누르면 값을 바꾸는 set 기능으로 인해 count+1 된 값으로 변경된다.
Hook 사용하기
useState 처럼 use ~ 로 시작되는 리액트의 특별한 함수들을 hook이라고 하는데, 기존의 훅을 조합하여 자신만의 훅을 만들 수도 있다. 리액트에서 제공하는 훅은 https://ko.react.dev/reference/react/hooks 여기서 확인 가능!
Hook을 사용할 때는 몇가지 규칙을 지켜야 된다.
- 컴포넌트 최상위에서만 호출
- 반복문, 조건문 안에서 사용 금지(반복에서 사용하고 싶다면 컴포넌트로 추출하여 넣기)
컴포넌트 간에 데이터 공유하기
컴포넌트가 위 사진처럼 구성된 경우, 한쪽에서 카운트를 올리면 다른 한쪽 카운트는 변하지 않는다.
데이터를 공유하고 같이 업데이트 하기 위해서는 어떻게 해야 될까?
두 MyButton 컴포넌트가 동일한 count를 표시하고 함께 업데이트하려면, state를 상위에서 사용해야 된다.
그 다음 상위에서 사용된 state 값을 하위요소인 MyButton 에게 내려주면 된다.
코드로 표현하면 다음과 같다. 이렇게 부모 컴포넌트에서 자식 컴포넌트로 어떤 값을 내려주는 것을 props 라고 한다.
- 읽기 전용 (자식이 받은 props를 직접 수정할 수 없음)
- 부모 → 자식 한 방향으로만 전달
- 객체, 함수 등 모든 타입의 데이터 전달 가능
// 부모 컴포넌트
function ParentComponent() {
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>
);
}
- 버튼 클릭 → handleClick 함수 실행
- setCount(count + 1)로 숫자 증가
- 증가된 숫자가 props로 두 버튼에 전달됨
- 두 버튼이 같은 숫자를 보여줌
부모 컴포넌트에서 state를 관리하니까 자식 컴포넌트들이 같은 값을 공유할 수 있다.
'기술 > React.js' 카테고리의 다른 글
[문서] 리액트 공식문서 톱아보기: 컴포넌트 (0) | 2024.10.28 |
---|---|
react에서 vite로 env 설정해서 proxy 사용하기 (+CRA에서 proxy 설정) (0) | 2024.03.20 |
리액트에서 무한스크롤 구현하기(React-query, react-intersection-observer 사용) (1) | 2023.12.08 |
useState의 업데이트 방식에 따른 차이(함수형 업데이트) (0) | 2023.11.26 |
리액트에서 "불변성"이 중요한 이유 (0) | 2023.11.26 |