이번 프로젝트에서는 1차 프로젝트에서 사용한 기술 스택과는 조금 다른 부분이 생겼다.
일단 sass 대신 styled-component를 사용하고, 클래스 컴포넌트 대신 함수형 컴포넌트를 사용하게 되었다.
(추가적으로 git rebase....)
호기롭게 시작했는데 익숙지 않은 방식으로 코드를 작성하다 보니 진도가 조금 느린듯한 감도 있다.
하지만 이번 프로젝트에는 조급해하지 않고 기능구현보다는 코드의 퀄리티에 좀 더 신경을 쓰려고 한다.
그렇기 때문에 이번주에는 학습하는데 시간이 조금 더 걸렸다.
특히 hooks를 이해하고 사용하는 데에 시간이 많이 걸렸고 아직도 더 걸릴 예정이다.😂
🪝Hook은 기본적으로 함수이다!
별 특별할 것 없이 평상시에 아무렇지 않게 사용하던 함수와 똑같다.
하지만 이러한 함수를 react내에서 hook으로 사용할 때는 함수의 closure라는 개념을 알고 있어야
어떻게 hook이 컴포넌트의 state값을 상태 유지하는지 이해할 수 있다.
2021.01.27 - [개발/Javascript] - closure(클로저)
클로저를 활용한다면 정보를 캡슐화하여 지킬 수도 있고, 현재 정보의 상태를 기억할 수도 있기 때문에
컴포넌트 내의 state값을 활용할 수 있게 된다.
📣Hook의 기본 규칙!
- 최상위(at the top level)에서만 hook을 호출해야 한다.
- 리액트 함수 컴포넌트 내에서만 hook을 호출해야 한다. (custom hook에서는 호출 가능)
리액트는 특정 state의 구별을 hook이 호출되는 순서에 의존한다.
조건문이나 반복문내에서 hook을 호출할 경우 랜더링이 일어날 때마다 hook의 호출 순서를 보장할 수 없기 때문에
hook은 리액트 함수 컴포넌트 내의 최상위에서 호출 되어야 한다.
이번 글에서는 react에서 기본으로 제공하는 hook 중 useState와 useEffect에 대해 정리해 보려고 한다.
🪝useState
useState는 class 컴포넌트의 state값과 setState 함수를 선언해 주는 함수라고 생각하면 이해가 편하다.
//클래스형 컴포넌트에서 state값 선언
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 5
};
}
//함수형 컴포넌트에서 state값 선언
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(5); //비구조 할당
위의 예에서는 count라는 이름의 state값을 선언하였다.
클래스형 컴포넌트에서는 setState함수를 통해 state값을 변경하였지만,
함수형 컴포넌트에서는 state 값 선언시에 동시에 선언한 setCount 함수를 통해 count state값을 변경해 줄 수 있다.
(setCount라는 이름은 정해진 규칙은 없지만 보통 'set + state명' 으로 선언하는 것이 컨벤션이다.)
useState(5)의 5는 count에 할당할 초기값을 useState의 인자로 전달한 것이다.
const useState = (init = undefined) => {
let value = init
const getter = () => value // 클로저
const setter = next => (value = next) // 클로저
return [getter, setter]
}
const [state, setState] = useState('클로저')
위 코드는 useState의 구조를 간략하게 보여준다.
함수는 return시 생명이 다하기 때문에 가비지 컬렉팅에 의해 메모리에서 지워지는 것이 맞지만,
useState 내부에서 선언한 지역변수를 내부에서 선언한 함수가 참조하고 있기에, 클로저 특성에 의해 지워지지 않는다.
이러한 함수형 컴포넌트에서의 hook을 사용한 statet값 선언은 코드를 상당히 간략화해준다.
🪝useEffect
useEffect에 대해 react 공식문서에서는 이렇게 명시하고 있다. 📜
Effect Hook을 사용하면 함수 컴포넌트에서 side effect를 수행할 수 있습니다.
리액트의 class 생명주기 메서드에 친숙하다면, useEffect Hook을 componentDidMount와 componentDidUpdate, componentWillUnmount가 합쳐진 것으로 생각해도 좋습니다.
hook에 대해 공부하면서 useEffect에 대해 느낀 점은 어렵다기보다는 난감하다(?)라는 느낌이었다. 🤔
어떻게 사용하라는 건지, 사용해보면 내가 사용한 방법이 맞는지, 뭔가 개운치 못한 느낌이었다.😧
클래스형 컴포넌트에 비해서 굉장히 간략해지고 자유도가 높아져서 그런 것 같다고 예상하지만,
이 부분에 있어서는 좀 더 익숙해져 봐야 할 것 같다.
useEffect의 사용은 먼저 크게 두 가지로 나눌 수 있다.
🧼clean-up이 필요한 effect와 필요 없는 effect.
useEffect hook은 기본적으로 컴포넌트가 렌더 될 때마다 인자로 받게 된 effect(함수)를 실행한다.
이러한 effect 중에는 컴포넌트가 해제될 경우(componentWillUnmount) 동작을 멈추거나 다른 동작을 실행해야 하는 경우가 있는데,
이러한 경우를 useEffect에서 clean-up이 필요한 경우라고 할 수 있다.
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
위 코드에서 보이듯이 clean-up시 실행할 함수는 return을 통해 명시해준다.
useEffect는 2개의 인자를 받을 수 있는데 2번째 인자에 무엇이 들어가느냐에 따라 useEffect를 실행할지 말지를 결정해 줄 수 있다.
//컴포넌트가 렌더될 때마다 실행
useEffect(() => {
document.title = `You clicked ${count} times`;
});
//컴포넌트가 초기 마운티 되는 경우 한번만 실행
useEffect(() => {
document.title = `You clicked ${count} times`;
}, []);
//count 값이 변경될 때마다 실행
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
지금까지 내가 사용하고 이해하고 있는 부분은 여기까지인 것 같다.
프로젝트를 진행하면서 추가적으로 hook에 익숙해 지면서 더 많은 hook을 알아보려고 한다.
'개발 > React' 카테고리의 다른 글
TIL #26 Context API & Redux (전역상태관리) (0) | 2021.05.17 |
---|---|
TIL #15 조건부 렌더링 (0) | 2021.03.20 |
TIL #14 동적라우팅 (0) | 2021.03.19 |
TIL #13 합성이벤트, key Prop (0) | 2021.03.10 |
TIL #11 state & props (0) | 2021.03.05 |