Hook?
처음에 React는 클래스 컴포넌트로 컴포넌트를 관리했다. 클래스 안에서 componentDidMount, componentDidUpdate, componentWillUnmount 라는 함수를 사용해 생명주기에 따른 데이터를 처리했다. 그러다 클래스 컴포넌트보다 더 간결한 함수 컴포넌트가 생겨났고, 함수 컴포넌트 안에서 사용할 수 있는 생명주기 함수가 필요했다. 그래서 생겨난 것이 Hook 개념이다.
아래는 버튼을 클릭하면 count 변수의 값이 1씩 증가하는 예제 코드이다. 첫번째가 클래스 컴포넌트로 작성한 코드이고 두번째가 함수 컴포넌트인데, 한눈에 봐도 함수 컴포넌트가 더 간략한 것을 볼 수 있다.
import React, { Component } from "react";
class ClassComponent extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
handleIncrement = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<h2>Class Component</h2>
<p>Count: {this.state.count}</p>
<button onClick={this.handleIncrement}>Increase</button>
</div>
);
}
}
export default ClassComponent;
import React, { useState } from "react";
const FunctionComponent = () => {
const [count, setCount] = useState(0);
return (
<div>
<h2>Function Component</h2>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
</div>
);
};
export default FunctionComponent;
이러한 이유로 사람들이 점점 함수 컴포넌트와 Hook을 사용하기 시작했다.
React에는 5가지 기본적인 훅이 있다. 물론 custom으로 훅을 만들 수도 있다. default 훅에는 useState, useEffect, useMemo, useCallback, useRef 이 있다. 5개의 훅 모두 use로 시작하는데, 개발자들이 훅이라는 것을 쉽게 알아챌 수 있도록 한 네이밍 규칙이다.
useState - props and state?
state가 뭘까? state는 props와 함께 React에서 컴포넌트의 동적 데이터를 관리하는 개념이다. props와 state의 개념을 예제를 통해 알아보자.
React는 모든 화면을 컴포넌트 단위로 구성해 그리는데, props는 부모-자식 간 관계에서 데이터를 주고받을 때 사용한다. 정확히는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 사용한다.
Parent 컴포넌트에서 Child 컴포넌트를 생성하고 있다. 이때 name이라는 변수에 값을 넣어 전달해주고 있는데, 이게 바로 props이다.
const Parent = () => {
return (
<div>
<Child name="Alice" />
</div>
);
};
받아서 쓸 때에는 아래와 같이 파라미터 형식으로 받으면 끝이다.
const Child = ({ name }) => {
return (
<div>
<p>Hello, {name}!</p>
</div>
);
};
그럼 state는 뭘까?
state는 현재 컴포넌트에서 렌더링의 기준이 된다고 할 수 있다. state로 지정한 변수가 변하면 React는 컴포넌트를 다시 그리기 때문이다. 그래서 state는 렌더링과 관련된 변수로 구성해야 불필요한 재렌더링이 발생하지 않는다.
useState의 return 형태는 배열이다. 배열의 첫번째 값은 변수, 두번째 값은 변수의 값을 변경할 수 있는 함수를 반환한다. 즉, count 변수의 값을 변경하고 싶으면 count += 1 이게 아니라 setCount(count+1) 로 변경해야 한다.
const [변수, set변수] = useState(초기값);
const [count, setCount] = useState(0);
useEffect
생명주기 함수 대신 사용할 수 있는 훅이다. 사용에 따라 컴포넌트가 랜더링될 때, 업데이트될 때, 언마운트될 때의 동작을 특정할 수 있다.
파라미터로 이펙트 동작을 지정할 함수와 의존성 배열을 지정한다. 보통 이펙트 함수는 화살표 함수로 아래와 같이 정의한다. 우선, 의존성 배열이 있으면 해당 배열 안의 변수가 변경될 때마다 이펙트 함수가 동작한다. 의존성 배열이 없으면 처음에 컴포넌트가 생성될 때 즉, 마운트될 때만 이펙트 함수가 동작한다. 또 의존성 배열이 없는데 return 함수가 정의되어 있으면, return 함수의 내용은 컴포넌트가 종료될 때, 언마운트될 때 동작해 주로 정리 함수로 사용된다.
useEffect(이펙트 함수, 의존성 배열);
useEffect(() => {
console.log(`Count updated: ${count}`);
}, [count]); // count가 변경될 때마다 실행됨
useEffect(() => {
console.log("Component mounted!");
}, []); //마운트될 때 한 번만 수행
useEffect(() => {
return () => {
console.log("Component unmounted!");
};
}, []); //언마운트될 때 한 번만 수행