Hook
은 클래스 컴포넌트에서만 사용할 수 있었던 state(상태)
관리와 lifecycle(라이프 사이클)
관리 기능을 함수 컴포넌트에서도 사용할 수 있도록 연동(hook in)해주는 함수를 의미하며, 이러한 Hook들의 모음을 Hooks
라고 한다.
Hook
은 공식문서에 따르면 React 버전 16.8부터 새로 추가된 요소이다. Hook
을 이용하게 되면 기존의 Class 방식으로 코드를 작성할 필요 없이 상태 값과 여러 React의 기능을 사용할 수 있다. 기존에서는 생명주기 같이 상태를 관리하기 위해서는 클래스(Class) 컴포넌트에서 작성해주었는데, Hook이 나온 이후로는 함수 컴포넌트에서도 충분히 상태를 관리할 수 있게되었다.
React는 useState
와 같은 내장 Hook
을 몇 가지 제공하고 있으며, 컴포넌트 간에 상태 관련 로직을 재사용하기 위해 Hook을 직접 만드는 것(custom hook)도 가능하다.
Hook
은 클래스 컴포넌트 안에서는 동작하지 않으며 오로지 함수 컴포넌트 내에서만 사용해야 한다고 했는데(일반 Javascript 함수에서도 사용할 수 없음), 그렇다면 Hook
을 호출할 수 있는 곳은 어디일까?
🛎 함수 컴포넌트 내부
🛎 custom Hook 내부
Hook
은 항상 함수 컴포넌트 내의 최상위(at the top level)에서만 호출해야 한다. 이러한 규칙을 따른다면 해당 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 여러 개의 Hook이 호출되는 것을 보장할 수 있다. 왜냐하면 React가 여러 Hook들을 구분할 수 있는 유일한 정보는 Hook이 사용된 순서이기 때문이다.
또한 반복문, 조건문, 중첩된 함수 내에서는 Hook을 호출하면 안된다. 특정 조건에 부합하지 않는 경우 Hook을 호출하지 않게 되고, 그렇다면 Hook이 사용된 순서가 섞이기 때문이다.
Hook이 제공하는 내장 API에는 useState
와 useEffect
가 있는데, 이를 알아보기 전에 STATE부터 알아보자.
React에서 state
란 컴포넌트 내부에서 가지고 있는 컴포넌트의 상태값을 의미하며, 해당 컴포넌트가 UI에 보여줄 정보를 결정할 때 사용할 수 있는 상태값을 의미한다. state
는 컴포넌트 내에서 정의하고 사용하며 얼마든지 변경할 수 있다.
state는 UI에 보여줄 정보를 결정할 때 사용할 수 있는 상태값이라고 했는데,, 그렇다면 함수 컴포넌트에서 state를 어떻게 선언할까?
먼저 state를 사용하기 위해 useState 함수를 import한 후에 사용해야 한다. useState 함수는 Hook의 일종으로 내장되어 있는 react로부터 가져올 수 있다.
useState hook을 사용할 때는 useState hook으로부터 반환되는 값을 구조 분해 할당을 통해 각각의 변수에 담아서 사용한다.
그렇다면 useState hook의 호출 결과로 반환되는 배열의 요소는 각각 무엇인지 알아보자. 자세한 이야기는 useState 더보기
const [state, setState function] = useState(defaultValue)
⭐️ state
의 값을 변경할 때 단순히 다른 값을 할당하는 것이 아니라 useState
함수로부터 반환된 두 번째 요소인 setState
를 사용해야 한다!
//Example
import React, { useState } from 'react';
const Main = () => {
const [color, setColor] = useState('red');
return (
<>
<h1 style={{ backgroundColor: color }}>여기는 메인페이지입니다.</h1>
<button onClick={() => setColor('blue')}>색상 바꾸기</button>
</>
);
};
export default Main;
여기서 color의 값이 버튼을 누를 때 바뀌는 것과 이에 따라 화면에도 바뀐 값으로 적용되는 원리를 알아보자면, state
의 값을 변경하려면 color = “blue”
라고 할당하는 것이 아닌 꼭 setColor(”blue”)
함수를 사용해야 한다. 왜냐하면 단순 할당으로는 바뀐 값을 기준으로 화면이 다시 그려지지 않는데 비해, setColor
함수를 통해서 변경하게 되면 바뀐 값을 기준으로 다시 화면을 그려주는 것을 확인할 수가 있기 때문이다. 다시 말해 setColor
를 통해 color의 값을 변경해야만 값의 업데이트와 리렌더링의 효과를 볼 수 있다.
UI에 보여줄 정보를 결정할 때 사용하는 상태값인 state
값을 부모 컴포넌트에서 선언되었지만 자식 컴포넌트로 데이터를 전달하기 위해 사용되는 props
로 전달해서 활용하는 방법 또한 중요하다.
// Parent.js (부모 컴포넌트)
import React, { useState } from 'react';
import Child from './Child';
const Parent = () => {
const [color, setColor] = useState('red');
const changeColor = () => {
setColor('blue');
};
return (
<>
<div>부모 컴포넌트입니다.</div>
<Child color={color} change={changeColor} />
</>
);
};
export default Parent;
state
값을 선언하고, props
로 넘겨준다고 해서 달라지는 점은 없다. 변수, 함수를 props
로 넘겨주는 것과 똑같다. useState
hook을 통해 state
를 선언하고, 그 값을 알맞은 이름으로 넘겨주면 된다. 위 예시에서는 state
로 관리하고 있는 color 값을 color라는 이름으로 넘겨주었고, state
값을 업데이트하는 함수 setColor는 chageColor 함수를 만들어서 change라는 이름으로 넘겨줬다.
state
는 setState
함수를 통해서만 변경할 수 있다. 그런데 setState
함수는 부모 컴포넌트에 있다. 그렇다면 자식 컴포넌트에서 state를 변경하고 싶을 때는 어떻게 해야할까?
// Child.js (자식 컴포넌트)
import React from 'react';
const Child = (props) => {
console.log(props); // {color: 'red', change: () => {setColor('blue')}}
return (
<>
<div>자식 컴포넌트입니다.</div>
<p>{props.color}</p>
<button onClick={props.change}>색상 바꾸기</button>
</>
);
};
export default Child;
자식 컴포넌트인 Child는 props
를 통해서 state
값인 color와 color 값을 업데이트 시킬 수 있는 함수를 받아온다. props
객체로 감싸져 있기 때문에 부모 컴포넌트로부터 받아온 상태값을 사용하고 싶을 때는 {props.color}
로, 그 값을 클릭 이벤트를 통해 업데이트 함수를 실행시키고 싶다면 클릭 이벤트 핸들러에 {props.change}
를 연결해 실행시킨다.
결국, 유저가 자식 컴포넌트에 있는 “색상 바꾸기”라는 버튼을 누르면 실행되는 함수는 부모 컴포넌트 내에 있는 setColor
함수가 되는 것이다. 앞서 언급한 듯이 state
는 선언된 곳에서 업데이트가 되어야 하지만 이처럼 props
를 이용해서 state
끌어올리기를 한다면, 자식 컴포넌트에서도 원하는 상태값을 제어할 수 있다.
출처 : wecode