리액트에는 조건을 작성하는 특별한 문법이 존재하지 않으므로 자바스크립트에서 사용하던 조건문을 그대로 사용하면 된다.
let content;
if (isLoggedIn) {
content = <AdminPanel />
} else {
content = <LoginForm />
}
return (
<div>
{conent}
</div>
);
if ... else
대신 삼항 연산자를 사용할 수 있으며 else
문이 필요없는 경우 다음 코드로 대체할 수 있다.
return (
<div>
{isLoggedIn && <AdminPanel />}
</div>
);
for
문이나 array의 map()
을 이용하여 컴포넌트 배열을 반환할 수도 있다.
const products = [
{ name: 'Apple', id: 1 },
{ name: 'Banana', id: 2 },
{ name: 'Carrot', id: 3 },
];
const listItems = products.map(product =>
<li key={product.id}>
{product.name}
</li>
);
export default function App() {
return (
<ul>{listItems}</ul>
);
}
컴포넌트 내에 이벤트 핸들러 함수를 선언하여 이벤트에 응답하도록 만들 수 있다.
function MyButton() {
function handleClick() {
alert('Click!!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
onClick
은 마우스 이벤트 중 하나로, 사용자가 HTML 요소를 클릭할 때 발생하는 이벤트다.
컴포넌트에 정보를 저장하고 출력해보자. 지금 만들 컴포넌트는 버튼을 클릭할 때마다 그 수를 하나씩 증가시키는 버튼이다. 이것을 구현하기 위해서는 컴포넌트에 state를 추가해야 한다.
useState()
는 current state와 current state를 업데이트하는 함수를 가진다. 아무 이름이나 지정할 수 있지만[something, setSomething]
형식을 권장한다.
import React, { useState } from 'react';
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count+1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
Hook은 리액트 버전 16.8부터 리액트 요소로 새롭게 추가 되었다. Hook을 이용하면 기존 클래스 바탕의 코드를 작성할 필요 없이 상태값과 여러 리액트 기능을 사용할 수 있다. 앞서 살펴본 useState
가 Hook의 대표적인 예다.
💥 Built-in React Hooks
State Hooks : state는 컴포넌트가 사용자 입력값과 같은 정보를 기억할 수 있도록 만든다.
useState
: 직접적으로 업데이트 할 수 있는 상태 변수 선언useReducer
: 리듀서 함수 내에 상태 변수와 업데이트 로직 선언
useState
와useReducer
는 초기값을 전달하고 상태값과 상태를 설정하는 함수를 반환한다는 점에서 동일하다. 하지만useReducer
는 초기값과 함께 reducer function을 파라미터로 전달해야 한다.
Context Hooks : context를 사용하면 컴포넌트가 props를 전달하지 않고 멀리 떨어진 부모로부터 정보를 받을 수 있다. Context hook에는 useContext
가 있다.
Ref Hooks
Refs는 컴포넌트가 랜더링에 사용되지 않는 정보를 가지고 있는 것을 허용한다. state와 달리 ref를 갱신하는 것은 컴포넌트를 다시 렌더링하지 않는다는 것을 의미한다. refs는 built-in browser API처럼 리액트 시스템 이외의 것과 작업할 때 유용하다.
ex. useRef
, useImperativeHandle
Effect Hooks
effects를 사용하면 컴포넌트가 외부 시스템에 연결하여 동기화할 수 있다. effects는 네트워크, 브라우저 DOM, 애니메이션 처리를 포함한다.
useEffect
: 컴포넌트를 외부 시스템과 연결한다.userLayoutEffect
: 브라우저가 리페인팅을 하기 전에 레이아웃을 측정한다.useInsertionEffect
: 리액트가 DOM을 변경하기 전에 라이브러리가 동적 CSS를 삽입한다.Performance Hooks
리랜더링을 최적화하는 가장 흔한 방법은 불필요한 작업을 건너뛰는 것이다. 예를 들어 이전 렌더 이후로 데이터가 변경되지 않았으면 리렌더링을 스킵한다.
불필요한 연산이나 불필요한 리렌더링을 건너뛰려면 다음 후크 중 하나를 사용하면 된다.
useMemo
: 계산 결과를 캐싱한다.useCallback
: 메모제이션된 콜백을 반환한다.화면 전체를 갱신해야 하는 경우가 발생하면 리렌더링을 거너뛸 수 없다. 이 경우에는 blocking과 non-blocking을 구분하여 성능을 개선할 수 있다.
useTransition
: (non-blocking) UI를 블락하지 않고 상태를 갱신한다.useDeferredValue
: (blocking) UI 업데이트를 연기하고 다른 부분을 먼저 갱신한다.
리액트 컴포넌트는 서로 통신하기 위해 props를 사용한다. 모든 부모 컴포넌트는 props를 전달하며 자식 컴포넌트들에 정보를 전달한다. props는 HTML 속성이나 객체, 배열, 함수를 포함한 어느 자바스크립트 값이든 될 수 있다.
User
에 props 전달하기person
, size
// parent
export default function Profile() {
return (
<User
person={{name: 'John', imageId: '1bX5QH6'}}
size={100}
/>
);
}
// child
function User ({person, size}) {
return (
<img
className='user'
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
props는 부모와 자식 컴포넌트를 독립적으로 바라보도록 만든다. 예를 들어
Profile
에서person
과size
값을 수정할 때User
를 고려할 필요가 없다.
💥 props를 사용하는 두 가지 방법
props는 컴포넌트의 유일한 인자다.
function User({person, size}) {...}
function User(props) {
let person = props.person;
let size = props.size;
...
}
참고자료
React docs : Quick Start
React docs : Built-in React Hooks