December 05, 2020
이 포스트는 공식문서를 참조한 글입니다!
더욱 많은 정보를 얻고 싶으시다면 공식문서로…
리액트 컴포넌트에는 두가지 종류가 있었죠! 바로 클래스형과 함수형 컴포넌트였는데요,
둘의 가장 큰 차이점은 Class형 컴포넌트는 state가 있고, Function형은 state가 없다는 것이라고 했었죠!
하지만 Hook과 함께라면 function형 컴포넌트에서도 state와 lifecycle 메소드를 사용할 수 있게 됩니다.
컴포넌트 사이에서 상태와 관련된 로직을 재사용하기 어렵습니다.
복잡한 컴포넌트들은 이해하기 어렵습니다.
Class는 사람과 기계를 혼동시킵니다.
기존의 class가 코드의 재사용성을 힘들게 만들고, this가 여러가지 부작용을 일으키는 문제점이 있었습니다.
하지만 그렇다고 React 측에서 Class component를 삭제할 계획은 없다고 합니다!
class component와 hook을 사용한 컴포넌트는 완벽하게 호환됩니다.
먼저 예를 들어보겠습니다
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
import React, { useState } from 'react';
function Example() {
// 새로운 state 변수를 선언하고, count라 부르겠습니다.
const [count, setCount] = useState(0); //초기값 0
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
위 코드가 class component, 아래는 같은 component를 hook을 사용해 만든 것입니다.
두 컴포넌트는 완전히 같은 일을 하고 있지만, 확실히 아래 코드가 깔끔하고 보기 좋죠? (this…넘모싫다…)
이제 두 컴포넌트의 차이점에 대해 자세하게 뜯어보겠습니다
함수형에서는 React로부터 useState를 import해와서 사용했습니다.
const [state명, state를_설정해주는_함수명] = useState(초기값);
useState는 react 내장 hook입니다. 함수형 컴포넌트 안에서 state를 쓰게 해줍니다!
배열의 첫번째 값은 state가 되고, 두번째 값은 그 state의 값을 설정해주는 함수입니다.
//클래스형
this.state = {
count : 0
}
//항수형
const [count, setCount] = useState(0);
//클래스형
<p>You clicked {this.state.count} times</p>
//함수형
<p>You clicked {count} times</p>
class형에서는 this.state를 꼭 입력해줘야만 state 값을 가져올 수 있었지만
함수형에서는 그냥 count만 써줘도 끝! 넘나 깔끔쓰~
//클래스형
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
//함수형
<button onClick={() => setCount(count + 1)}>
Click me
</button>
클래스형에서는 state값을 변경해주기위해서 this.setState()를 호출해줘야했습니다.
하지만 함수 컴포넌트에서는 초기 state 선언 때 받아왔던 setCount 함수를 호출합니다.
useEffect 함수를 사용하면 함수형 컴포넌트에서도 라이프사이클을 사용할 수 있습니다.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
이전까지 사용하던 컴포넌트에 componentDidMount와 componentDidUpdate를 통해서 문서의 제목을 변경해주는 예제입니다.
이것을 함수형 컴포넌트로 바꿔준다면..!
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// componentDidMount, componentDidUpdate와 같은 방식으로
useEffect(() => {
// 브라우저 API를 이용하여 문서 타이틀을 업데이트합니다.
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
이렇게 됩니다! 이제 useEffect에 대해서 자세히 알아봅시다.
useEffect(() => {
// 첫번째 렌더링 + 모든 업데이트 때 실행됨 (componentDidMount + componentDidUpdate)
return () => {
// 컴포넌트가 언마운트될 때 실행됨 (componentWillUnmount)
}
});
useEffect함수는 이렇게 생겼습니다. useEffect 는 두개의 인자를 받는데, 첫번째는 함수입니다.
첫번째 인자로 들어가는 함수의 안에 들어가는 코드들은 첫번째 렌더링 + 업데이트 후 실행되고,
return 뒤의 함수에 들어가는 코드들은 컴포넌트가 언마운트 될때 실행됩니다.
만약 컴포넌트가 unmount될때 실행해야 할 내용이 없다면 return 문은 생략해도 됩니다.
그를 위해서 있는 옵션이 바로 의존성 배열입니다! 바로 위에서 useEffect에서는 두개의 인자를 받는다고 했었죠?
그 두번째 인자인 의존성 배열을 사용해서 useEffect가 실행되는 조건을 설정할 수 있습니다.
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
이 useEffect함수는 count state가 업데이트 될때만 실행됩니다.
useEffect(() => {
document.title = `You clicked ${count} times`;
}, []);
이 useEffect함수는 첫번째 렌더링에만 실행됩니다. (componentDidMount)