class없이 state를 사용할 수 있는 새로운 기능
함수형 컴포넌트에서도 React state와 생명 주기 기능을 연동 할 수 있게 해주는 기능
Hook을 사용하면 클래스형 컴포넌트 없이도 상태 관리, 사이드 이팩트 처리등을 할 수 있다.
import React, { useState } from "react";
const Component = () => {
const [value, setValue] = useState(0);
const upCount = () => {
setValue(value + 1);
};
const downCount = () => {
setValue(value - 1);
};
return (
<div>
<p>
카운터 값 <b>{value}</b>
</p>
<button onClick={upCount}>+1</button>
<button onClick={downCount}>-1</button>
</div>
);
};
export default Component;
버튼 클릭을 통해 state 값 변경하여 화면에 적용

출처: https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
사용 방법
useEffect(함수, deps)
함수: useEffect가 실행될때 작동할 작업, (return이 useEffect 내부에 있을 시 컴포넌트가
Unmount 될때 혹은 업데이트 되기 직전 return 함수 실행)
deps: 배열 형태, 값이 있으면 마운트 할때와 지정 값이 업데이트 될때 useEffect 실행
const Component = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`clicked ${count} times`);
}, []);
return (
<div>
<p>총 {count}번 클릭했습니다</p>
<button onClick={() => setCount(count + 1)}>클릭</button>
</div>
);
};
deps값에 빈 배열을 입력하면 컴포넌트가 마운트 될 때 한 번만 실행한다
const Component = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`clicked ${count} times`);
}, [count]);
return (
<div>
<p>총 {count}번 클릭했습니다</p>
<button onClick={() => setCount(count + 1)}>클릭</button>
</div>
);
};
count가 바뀔 때 마다 useEffect실행
const Component = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(`clicked ${count} times`);
return console.log(`total count ${count}`);
}, []);
return (
<div>
<p>총 {count}번 클릭했습니다</p>
<button onClick={() => setCount(count + 1)}>클릭</button>
</div>
);
};
return 뒤에 오는 함수를 clean up 함수라고 한다. unmount 시 필요한 작업을 작성한다
의존성 변수가 있다면 useEffect가 다시 실행되기 전에 호출됩니다.
컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술
현재 종속성과 이전 종속성을 비교하여 종속성이 변경되었는지 확인합니다.
useMemo(함수, 의존성 배열)
const Component = () => {
const [query, setQuery] = useState("");
const [items] = useState([
"Apple",
"Banana",
"Cherry",
"Date",
"Grape",
"Orange",
]);
const filteredItems = useMemo(() => {
return items.filter((item) =>
item.toLowerCase().includes(query.toLowerCase())
);
}, [query, items]);
return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search items..."
/>
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
};
이 코드에서는 query와 items이 변경될 때만 필터링 된 리스트를 다시 계산한다.
의존성 배열이 변하지 않으면 useMemo는 이전 계산한 필터링 된 리스트를 반환한다.
const ChildComponent = ({ props }) => {
console.log("ChildComponent rendered");
return <button onClick={props}>Increment</button>;
};
const Component = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
const handleClick = useCallback(() => {
setCount((prevCount) => prevCount + 1);
}, []);
return (
<div>
<p>Count: {count}</p>
<ChildComponent props={handleClick} />
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type something..."
/>
</div>
);
};
위 코드의 경우 handleClick함수가 부모 컴포넌트에서 자식 컴포넌트로 props로 전달된다.
이때 useCallback을 사용하지 않으면 부모 컴포넌트가 리랜더링 될 때,
handleClick함수가 새로 리랜더링 된다.
이 불필요한 리랜더링을 방지하기 위해 useCallback을 사용하여 함수를 미리 메모리에 저장해둔다
const Component = () => {
const [count, setCount] = useState(0);
const countRef = useRef(0);
useEffect(() => {
countRef.current = count;
}, [count]);
const showAlert = () => {
alert(`Latest count value: ${countRef.current}`);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={showAlert}>Show Alert</button>
</div>
);
};
이 코드에서는 useEffect가 cout가 변경 될 때마다 실행되고 변경된 count값을 countRef.current에 업데이트 한다. 이 때 변경된 countRef.current는 재랜더링되더라도 그 값을 유지한다.
import { useState, useEffect } from "react";
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return windowSize;
};
export default useWindowSize;
import React from "react";
import useWindowSize from "./useWindowSize";
const Component = () => {
const { width, height } = useWindowSize();
return (
<div>
<h1>Window Size</h1>
<p>Width: {width}</p>
<p>Height: {height}</p>
</div>
);
};
export default Component;
위 customhook을 통해 윈도우 크기 추적
useWindowSize란 훅을 제작 이 훅은 useState를 통해 windowSize를 반환한다.
useWindowSize훅에서는 useState로 윈도우의 크기를 측정하고 useEffect를 통해 변경되는
윈도우의 크기를 저장한다.