React Hook은 React의 특별한 함수로, 16.8 버전부터 추가되었다.
이전에는 class 위주의 코드 작성을 통해 state를 관리했었다.
그러나 class 위주의 state 관리는 component들 사이에서 상태 로직을 다시 사용하기 어렵고, 복잡한 component는 이해하기 힘들다.
또한 class를 사용할 때 this 키워드가 혼란을 주기도 하는 등 여러 단점이 존재한다.
이를 보완하고자 React Hook이 도입되었다.
React Hook은 function 위주의 코드 작성으로 state 관리가 가능하다.
따라서 기존의 코드를 다시 작성할 필요 없이 일부 component 안에서 hook을 사용할 수 있다.
대표적인 Hook으로는 useState, useEffect이 있고, useContext, useMemo 등의 Hook도 사용된다.
useState는 Hook 중 가장 많이 사용된다.
useState는 현재의 state 값과 이 값을 업데이트하는 함수의 쌍으로 이루어진다.
해당 Hook은 class component에서 this.state와 동일한 기능을 수행한다.
다음과 같이 class component로 state 변수를 선언할 수 있다.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
}
다음과 같이 useState로 state 변수를 선언할 수 있다. 초기 state 변수를 0으로 설정하였다.
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
}
useState에서 state 변수는 함수가 끝나도 사라지지 않으며, 업데이트하는 함수를 호출하여 state 변수 값을 변경할 수 있다.
다음과 같이 this로 호출하지 않아도 setCount 함수로 count 갱신이 가능하다.
<button onClick={() => setCount(count+1)}>
Click me
</button>
useEffect는 component가 렌더링될 때마다 어떤 특정 일을 수행하는데, 첫 번째 렌더링과 그 이후의 모든 업데이트에서 수행된다.
일반적으로 effect는 모든 렌더링을 완료한 후 발생하므로 의존성이 변경될 때마다 다시 생성된다.
그러나 이는 필요하지 않을 때에도 매번 effect가 재생성된다는 단점이 존재하므로, effect가 종송되어 있는 값의 배열을 useEffect의 두 번째 parameter로 사용한다.
따라서 배열의 값이 변경될 때에만 effect가 재생성 된다.
useEffect(() => {
document.title = `You clicked ${count} times`;
}. [count]);
위 코드는 useEffect의 두 번째 parameter가 존재하고, 따라서 count가 바뀔 때에만 effect를 재실행한다.
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count+1)}>
Click me
</button>
</div>
);
}
위 코드는 state 변수의 초기값을 0으로 설정하였고 그에 따라 useEffect가 실행된다.
button이 클릭되면 setCount 함수에 의해 state 변수의 값이 1 증가한다.
이 때 state 변수의 값이 변경되었으므로 useEffect도 다시 실행된다.
React에서 component 간에 props를 이용해 값을 전달할 수 있다.
그러나 여러 번 전달을 해야하거나 복잡한 경우 불편하기 때문에 useContext를 사용하는 것이 좋다.
createContext으로 context 객체를 생성한 뒤, useContext로 context 객체를 불러오면 저장된 값을 사용할 수 있다.
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
const ThemeContext = React.createContext(themes.light);
function App() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
위 코드에서 ThemeContext에 createContext로 context 객체를 생성하였다. 이후 저장해 놓은 context를 ThemedButton 함수에서 useContext로 불러와 사용하였다.
useMemo, useCallback 모두 memoization을 이용한다는 점은 같다.
하지만 useMemo는 memoization된 값을 반환하고, useCallback은 memoization된 콜백(함수)을 반환한다는 차이가 있다.
다음은 useCallback을 이용한 예시이다.
배열의 값이 변경될 때 실행되고, memoization된 콜백이 반환된다.ㄴ
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
다음은 useMemo를 이용한 예시이다.
배열의 값이 변경될 때 실행되고, memoization된 값이 반환된다.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
참고
https://ko.reactjs.org/docs/hooks-intro.html
https://ko.reactjs.org/docs/hooks-state.html
https://ko.reactjs.org/docs/hooks-effect.html
https://ko.reactjs.org/docs/hooks-reference.html