const [state, setState] = useState(initialState);
초깃값을 계산하는 코드가 복잡한 경우에 활용
const [state, setState] = useState(() => {
// ...
return initialState;
});
setState(nextState);
비동기 함수에서 최신 State 값을 가져와서 새로운 State 값을 만들 때
setState((prevState) => {
// ...
return nextState
});
컴포넌트 함수에서 사이드 이펙트
(리액트 외부의 값이나 상태를 변경할 때)에 활용하는 함수
useEffect(() => {
// ...
}, []);
useEffect(() => {
// ...
}, [dep1, dep2, dep3, ...]);
useEffect(() => {
// 사이드 이펙트
return () => {
// 정리
}
}, [dep1, dep2, dep3, ...]);
const ref = useRef();
// ...
return <div ref={ref}>안녕 리액트!</div>;
const node = ref.current;
if (node) {
// node를 사용하는 코드
}
함수를 매번 새로 생성하는 것이 아니라
디펜던시 리스트가 변경될 때만 함수를 생성
const handleLoad = useCallback((option) => {
// ...
}, [dep1, dep2, dep3, ...]);
자주 사용하는 Hook 코드들을 모아서 함수로 만들 수 있었다.
이때 useOOO 처럼 반드시 맨 앞에 use 라는 단어를 붙여서
다른 개발자들이 Hook이라는 걸 알 수 있게 해줘야 한다.
useHooks 나 streamich/react-hooks 라는 사이트를 보면
다양한 Custom Hook이 소개되어 있다.
간단한 예시
비동기 함수의 로딩, 에러 처리를 하는 데 사용할 수 있는 함수
function useAsync(asyncFunction) {
const [pending, setPending] = useState(false);
const [error, setError] = useState(null);
const wrappedFunction = useCallback(async (...args) => {
setPending(true);
setError(null);
try {
return await asyncFunction(...args);
} catch (error) {
setError(error);
} finally {
setPending(false);
}
}, [asyncFunction]);
return [pending, error, wrappedFunction];
}
toggle 함수를 호출할 때마다 value 값이 참/거짓으로 번갈아가며 바뀐다.
ON/OFF 스위치 같은 걸 만들 때 유용
function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
const toggle = () => setValue((prevValue) => !prevValue);
return [value, toggle];
}
start 를 실행하면 callback 이라는 파라미터로 넘겨 준 함수를
timeout 밀리초 마다 실행하고, stop 을 실행하면 멈춘다.
setInterval 이란 함수는 웹 브라우저에 함수를 등록해서
일정한 시간 간격마다 실행하게된다.
실행할 때마다 사이드 이펙트를 만들고,
사용하지 않으면 정리를 해줘야 한다.
clearInterval 이라는 함수를 실행해서
사이드 이펙트를 정리한다.
function useTimer(callback, timeout) {
const [isRunning, setIsRunning] = useState(false);
const start = () => setIsRunning(true);
const stop = () => setIsRunning(false);
useEffect(() => {
if (!isRunning) return;
const timerId = setInterval(callback, timeout); // 사이드 이펙트 발생
return () => {
clearInterval(timerId); // 사이드 이펙트 정리
};
}, [isRunning, callback, timeout]);
return [start, stop];
}