Hooks API Reference
These docs are old and wonโt be updated. Go to react.dev for the new React docs.
These new documentation pages teach modern React:
Hook๋ React 16.8์์ ์๋ก ์ถ๊ฐ๋ ๊ฐ๋ ์ ๋๋ค. Hook์ ํตํด class๋ฅผ ์์ฑํ์ง ์๊ณ ๋ state์ ๊ฐ์ React ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ํ์ด์ง๋ React์ ๋ด์ฅ๋ Hook API๋ฅผ ์ค๋ช ํฉ๋๋ค.
Hook์ด ์์ํ๋ค๋ฉด Hook ๊ฐ์๋ฅผ ๋จผ์ ์ฝ์ด ๋ณด๊ธฐ ๋ฐ๋๋๋ค. ํน์ frequently asked questions์์ ์ ์ฉํ ์ ๋ณด๋ฅผ ์ฐพ์ ์๋ ์์ต๋๋ค.
๊ธฐ๋ณธ Hook
useState
This content is out of date.
Read the new React documentation for
useState
.
const [state, setState] = useState(initialState);
์ํ ์ ์ง ๊ฐ๊ณผ ๊ทธ ๊ฐ์ ๊ฐฑ์ ํ๋ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค.
์ต์ด๋ก ๋ ๋๋ง์ ํ๋ ๋์, ๋ฐํ๋ state(state
)๋ ์ฒซ ๋ฒ์งธ ์ ๋ฌ๋ ์ธ์(initialState
)์ ๊ฐ๊ณผ ๊ฐ์ต๋๋ค.
setState
ํจ์๋ state๋ฅผ ๊ฐฑ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค. ์ state ๊ฐ์ ๋ฐ์ ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋๋ง์ ํ์ ๋ฑ๋กํฉ๋๋ค.
setState(newState);
๋ค์ ๋ฆฌ๋ ๋๋ง ์์ useState
๋ฅผ ํตํด ๋ฐํ๋ฐ์ ์ฒซ ๋ฒ์งธ ๊ฐ์ ํญ์ ๊ฐฑ์ ๋ ์ต์ state๊ฐ ๋ฉ๋๋ค.
์ฃผ์
React๋
setState
ํจ์ ๋์ผ์ฑ์ด ์์ ์ ์ด๊ณ ๋ฆฌ๋ ๋๋ง ์์๋ ๋ณ๊ฒฝ๋์ง ์์ ๊ฒ์ด๋ผ๋ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค. ์ด๊ฒ์ดuseEffect
๋useCallback
์์กด์ฑ ๋ชฉ๋ก์ ์ด ํจ์๋ฅผ ํฌํจํ์ง ์์๋ ๋ฌด๋ฐฉํ ์ด์ ์ ๋๋ค.
ํจ์์ ๊ฐฑ์
์ด์ state๋ฅผ ์ฌ์ฉํด์ ์๋ก์ด state๋ฅผ ๊ณ์ฐํ๋ ๊ฒฝ์ฐ ํจ์๋ฅผ setState
๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. ๊ทธ ํจ์๋ ์ด์ ๊ฐ์ ๋ฐ์ ๊ฐฑ์ ๋ ๊ฐ์ ๋ฐํํ ๊ฒ์
๋๋ค. ์ฌ๊ธฐ์ setState
์ ์์ชฝ ํํ๋ฅผ ์ฌ์ฉํ ์นด์ดํฐ ์ปดํฌ๋ํธ์ ์๊ฐ ์์ต๋๋ค.
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
</>
);
}
โ+โ์ โ-โ ๋ฒํผ์ ํจ์ ํ์์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ๊ฐฑ์ ๋ ๊ฐ์ด ๊ฐฑ์ ๋๊ธฐ ์ด์ ์ ๊ฐ์ ๋ฐํ์ผ๋ก ๊ณ์ฐ๋๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ฐ๋ฉด, โResetโ ๋ฒํผ์ ์นด์ดํธ๋ฅผ ํญ์ 0์ผ๋ก ์ค์ ํ๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ธ ํ์์ ์ฌ์ฉํฉ๋๋ค.
์ ๋ฐ์ดํธ ํจ์๊ฐ ํ์ฌ ์ํ์ ์ ํํ ๋์ผํ ๊ฐ์ ๋ฐํํ๋ค๋ฉด ๋ฐ๋ก ๋ค์ ์ผ์ด๋ ๋ฆฌ๋ ๋๋ง์ ์์ ํ ๊ฑด๋๋ฐ๊ฒ ๋ฉ๋๋ค.
์ฃผ์
ํด๋์ค ์ปดํฌ๋ํธ์
setState
๋ฉ์๋์๋ ๋ค๋ฅด๊ฒ,useState
๋ ๊ฐฑ์ ๊ฐ์ฒด(update objects)๋ฅผ ์๋์ผ๋ก ํฉ์น์ง๋ ์์ต๋๋ค. ํจ์ ์ ๋ฐ์ดํฐ ํผ์ ๊ฐ์ฒด ์ ๊ฐ ์ฐ์ฐ์์ ๊ฒฐํฉํจ์ผ๋ก์จ ์ด ๋์์ ๋ณต์ ํ ์ ์์ต๋๋ค.const [state, setState] = useState({}); setState(prevState => { // Object.assign would also work return {...prevState, ...updatedValues}; });
๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋
useReducer
๊ฐ ์๋๋ฐ ์ด๋ ์ฌ๋ฌ๊ฐ์ ํ์๊ฐ๋ค์ ํฌํจํ state ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐ์ ๋ ์ ํฉํฉ๋๋ค.
์ง์ฐ ์ด๊ธฐ state
initialState
์ธ์๋ ์ด๊ธฐ ๋ ๋๋ง ์์ ์ฌ์ฉํ๋ state์
๋๋ค. ๊ทธ ์ดํ์ ๋ ๋๋ง ์์๋ ์ด ๊ฐ์ ๋ฌด์๋ฉ๋๋ค. ์ด๊ธฐ state๊ฐ ๊ณ ๋น์ฉ ๊ณ์ฐ์ ๊ฒฐ๊ณผ๋ผ๋ฉด, ์ด๊ธฐ ๋ ๋๋ง ์์๋ง ์คํ๋ ํจ์๋ฅผ ๋์ ์ ๊ณตํ ์ ์์ต๋๋ค.
const [state, setState] = useState(() => {
const initialState = someExpensiveComputation(props);
return initialState;
});
state ๊ฐฑ์ ์ ์ทจ์
State Hook์ ํ์ฌ์ state์ ๋์ผํ ๊ฐ์ผ๋ก ๊ฐฑ์ ํ๋ ๊ฒฝ์ฐ React๋ ์์์ ๋ ๋๋ง ํ๋ค๊ฑฐ๋ ๋ฌด์์ ์คํํ๋ ๊ฒ์ ํํผํ๊ณ ๊ทธ ์ฒ๋ฆฌ๋ฅผ ์ข
๋ฃํฉ๋๋ค. (React๋ Object.is
๋น๊ต ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํฉ๋๋ค.)
์คํ์ ํํผํ๊ธฐ ์ ์ React์์ ํน์ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํ๋ ๊ฒ์ด ์ฌ์ ํ ํ์ํ ์๋ ์๋ค๋ ๊ฒ์ ์ฃผ์ํ์ธ์. React๊ฐ ๋ถํ์ํ๊ฒ ํธ๋ฆฌ์ ๊ทธ ์ด์์ผ๋ก ใ๋ ๊น๊ฒใ๋ ๊ด์ฌํ์ง ์์ ๊ฒ์ด๋ฏ๋ก ํฌ๊ฒ ์ ๊ฒฝ ์ฐ์ง ์์ผ์
๋ ๋ฉ๋๋ค๋ง, ๋ ๋๋ง ์์ ๊ณ ๋น์ฉ์ ๊ณ์ฐ์ ํ๊ณ ์๋ค๋ฉด useMemo
๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๊ฒ๋ค์ ์ต์ ํํ ์ ์์ต๋๋ค.
Batching of state updates
React may group several state updates into a single re-render to improve performance. Normally, this improves performance and shouldnโt affect your applicationโs behavior.
Before React 18, only updates inside React event handlers were batched. Starting with React 18, batching is enabled for all updates by default. Note that React makes sure that updates from several different user-initiated events โ for example, clicking a button twice โ are always processed separately and do not get batched. This prevents logical mistakes.
In the rare case that you need to force the DOM update to be applied synchronously, you may wrap it in flushSync
. However, this can hurt performance so do this only where needed.
useEffect
This content is out of date.
Read the new React documentation for
useEffect
.
useEffect(didUpdate);
๋ช ๋ นํ ๋๋ ์ด๋ค effect๋ฅผ ๋ฐ์ํ๋ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค.
๋ณํ, ๊ตฌ๋ , ํ์ด๋จธ, ๋ก๊น ๋๋ ๋ค๋ฅธ ๋ถ์์ฉ(side effects)์ (React์ ๋ ๋๋ง ๋จ๊ณ์ ๋ฐ๋ฅด๋ฉด) ํจ์ ์ปดํฌ๋ํธ์ ๋ณธ๋ฌธ ์์์๋ ํ์ฉ๋์ง ์์ต๋๋ค. ์ด๋ฅผ ์ํํ๋ค๋ฉด ๊ทธ๊ฒ์ ๋งค์ฐ ํผ๋์ค๋ฌ์ด ๋ฒ๊ทธ ๋ฐ UI์ ๋ถ์ผ์น๋ฅผ ์ผ๊ธฐํ๊ฒ ๋ ๊ฒ์ ๋๋ค.
๋์ ์ useEffect
๋ฅผ ์ฌ์ฉํ์ธ์. useEffect
์ ์ ๋ฌ๋ ํจ์๋ ํ๋ฉด์ ๋ ๋๋ง์ด ์๋ฃ๋ ํ์ ์ํ๋๊ฒ ๋ ๊ฒ์
๋๋ค. React์ ์์ํ ํจ์์ ์ธ ์ธ๊ณ์์ ๋ช
๋ น์ ์ธ ์ธ๊ณ๋ก์ ํ์ถ๊ตฌ๋ก ์๊ฐํ์ธ์.
๊ธฐ๋ณธ์ ์ผ๋ก ๋์์ ๋ชจ๋ ๋ ๋๋ง์ด ์๋ฃ๋ ํ์ ์ํ๋ฉ๋๋ค๋ง, ์ด๋ค ๊ฐ์ด ๋ณ๊ฒฝ๋์์ ๋๋ง ์คํ๋๊ฒ ํ ์๋ ์์ต๋๋ค.
effect ์ ๋ฆฌ
effect๋ ์ข
์ข
์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์์ ์ ๊ฑฐ๋ ๋ ์ ๋ฆฌํด์ผ ํ๋ ๋ฆฌ์์ค๋ฅผ ๋ง๋ญ๋๋ค. ๊ฐ๋ น ๊ตฌ๋
์ด๋ ํ์ด๋จธ ID์ ๊ฐ์ ๊ฒ์
๋๋ค. ์ด๊ฒ์ ์ํํ๊ธฐ ์ํด์ useEffect
๋ก ์ ๋ฌ๋ ํจ์๋ ์ ๋ฆฌ(clean-up) ํจ์๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๊ตฌ๋
์ ์์ฑํ๋ ๊ฒฝ์ฐ๋ ์๋์ ๊ฐ์ต๋๋ค.
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
// Clean up the subscription
subscription.unsubscribe();
};
});
์ ๋ฆฌ ํจ์๋ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฉ์ง๋ฅผ ์ํด UI์์ ์ปดํฌ๋ํธ๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ ์ ์ํ๋ฉ๋๋ค. ๋๋ถ์ด, ์ปดํฌ๋ํธ๊ฐ (๊ทธ๋ฅ ์ผ๋ฐ์ ์ผ๋ก ์ํํ๋ ๊ฒ์ฒ๋ผ) ์ฌ๋ฌ ๋ฒ ๋ ๋๋ง ๋๋ค๋ฉด ๋ค์ effect๊ฐ ์ํ๋๊ธฐ ์ ์ ์ด์ effect๋ ์ ๋ฆฌ๋ฉ๋๋ค. ์์ ์์์, ๋งค ๊ฐฑ์ ๋ง๋ค ์๋ก์ด ๊ตฌ๋ ์ด ์์ฑ๋๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค. ๊ฐฑ์ ๋ง๋ค ๋ถํ์ํ ์ํ์ด ๋ฐ์ํ๋ ๊ฒ์ ํํผํ๊ธฐ ์ํด์๋ ๋ค์ ์ ์ ์ฐธ๊ณ ํ์ธ์.
effect ํ์ด๋ฐ
componentDidMount
์ componentDidUpdate
์๋ ๋ค๋ฅด๊ฒ, useEffect
๋ก ์ ๋ฌ๋ ํจ์๋ ์ง์ฐ ์ด๋ฒคํธ ๋์์ ๋ ์ด์์ ๋ฐฐ์น์ ๊ทธ๋ฆฌ๊ธฐ๋ฅผ ์๋ฃํ ํ ๋ฐ์ํฉ๋๋ค. ์ด๊ฒ์ ๊ตฌ๋
์ด๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ค์ ํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ค์์ ๊ณตํต์ ์ธ ๋ถ์์ฉ์ ์ ํฉํฉ๋๋ค. ์๋๋ฉด ๋๋ถ๋ถ์ ์์
์ด ๋ธ๋ผ์ฐ์ ์์ ํ๋ฉด์ ์
๋ฐ์ดํธํ๋ ๊ฒ์ ์ฐจ๋จํด์๋ ์ ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ทธ๋ ์ง๋ง, ๋ชจ๋ effect๊ฐ ์ง์ฐ๋ ์๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ์ฉ์์๊ฒ ๋
ธ์ถ๋๋ DOM ๋ณ๊ฒฝ์ ์ฌ์ฉ์๊ฐ ๋
ธ์ถ๋ ๋ด์ฉ์ ๋ถ์ผ์น๋ฅผ ๊ฒฝํํ์ง ์๋๋ก ๋ค์ ํ๋ฉด์ ๋ค ๊ทธ๋ฆฌ๊ธฐ ์ด์ ์ ๋๊ธฐํ ๋์ด์ผ ํฉ๋๋ค. (๊ทธ ๊ตฌ๋ถ์ด๋ ๊ฐ๋
์ ์ผ๋ก๋ ์๋์ ์ด๋ฒคํธ ๋ฆฌ์ค๋์ ๋ฅ๋์ ์ด๋ฒคํธ ๋ฆฌ์ค๋์ ์ฐจ์ด์ ์ ์ฌํฉ๋๋ค) ์ด๋ฐ ์ข
๋ฅ์ effect๋ฅผ ์ํด React๋ useLayoutEffect
๋ผ๋ ์ถ๊ฐ์ ์ธ Hook์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๊ฒ์ useEffect
์ ๋์ผํ ์๊ทธ๋์ฒ๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ๊ทธ๊ฒ์ด ์ํ๋ ๋์๋ง ์ฐจ์ด๊ฐ ๋ฉ๋๋ค.
Additionally, starting in React 18, the function passed to useEffect
will fire synchronously before layout and paint when itโs the result of a discrete user input such as a click, or when itโs the result of an update wrapped in flushSync
. This behavior allows the result of the effect to be observed by the event system, or by the caller of flushSync
.
Note
This only affects the timing of when the function passed to
useEffect
is called - updates scheduled inside these effects are still deferred. This is different thanuseLayoutEffect
, which fires the function and processes the updates inside of it immediately.
Even in cases where useEffect
is deferred until after the browser has painted, itโs guaranteed to fire before any new renders. React will always flush a previous renderโs effects before starting a new update.
์กฐ๊ฑด๋ถ effect ๋ฐ์
effect์ ๊ธฐ๋ณธ ๋์์ ๋ชจ๋ ๋ ๋๋ง์ ์๋ฃํ ํ effect๋ฅผ ๋ฐ์ํ๋ ๊ฒ์ ๋๋ค. ์ด์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์์กด์ฑ ์ค ํ๋๊ฐ ๋ณ๊ฒฝ๋๋ค๋ฉด effect๋ ํญ์ ์ฌ์์ฑ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ ์ด๊ฒ์ ์ด์ ์น์
์ ๊ตฌ๋
์์์ ๊ฐ์ด ์ผ๋ถ ๊ฒฝ์ฐ์๋ ๊ณผ๋ํ ์์
์ผ ์ ์์ต๋๋ค. source
props๊ฐ ๋ณ๊ฒฝ๋ ๋์๋ง ํ์ํ ๊ฒ์ด๋ผ๋ฉด ๋งค๋ฒ ๊ฐฑ์ ํ ๋๋ง๋ค ์๋ก์ด ๊ตฌ๋
์ ์์ฑํ ํ์๋ ์์ต๋๋ค.
์ด๊ฒ์ ์ํํ๊ธฐ ์ํด์๋ useEffect
์ ๋ ๋ฒ์งธ ์ธ์๋ฅผ ์ ๋ฌํ์ธ์. ์ด ์ธ์๋ effect๊ฐ ์ข
์๋์ด ์๋ ๊ฐ์ ๋ฐฐ์ด์
๋๋ค. ์ด๋ฅผ ์ ์ฉํ ์๋ ์๋์ ๊ฐ์ต๋๋ค.
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
์ ์ด์ , props.source
๊ฐ ๋ณ๊ฒฝ๋ ๋์๋ง ๊ตฌ๋
์ด ์ฌ์์ฑ๋ ๊ฒ์
๋๋ค.
์ฃผ์
์ด ์ต์ ํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๊ฐ์ ๋ฐฐ์ด์ด ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋๊ณ effect์ ์ฌ์ฉ๋๋ ์ปดํฌ๋ํธ ๋ฒ์์ ๋ชจ๋ ๊ฐ๋ค(์๋ฅผ ๋ค์ด, props์ state์ ๊ฐ์ ๊ฐ๋ค)์ ํฌํจํ๊ณ ์๋์ง ํ์ธํ์ธ์. ๊ทธ๋ ์ง ์๋ค๋ฉด ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ ์ด์ ๋ ๋๋ง์์ ์ค์ ๋ ์ค๋๋ ๊ฐ์ ์ฐธ์กฐํ๊ฒ ๋ ๊ฒ์ ๋๋ค. how to deal with functions์ array values change too often ํ ๋ ๋ฌด์์ ํ ๊ฒ์ธ์ง์ ๋ํด์ ์กฐ๊ธ ๋ ์์๋ณด์ธ์.
effect๋ฅผ ์ํํ๊ณ (mount๋ฅผ ํ๊ฑฐ๋ unmount ํ ๋) ๊ทธ๊ฒ์ ํ ๋ฒ๋ง ์คํํ๊ณ ์ถ๋ค๋ฉด ๋ ๋ฒ์งธ ์ธ์๋ก ๋น ๋ฐฐ์ด(
[]
)์ ์ ๋ฌํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด effect๋ React์๊ฒ props๋ state์์ ๊ฐ์ ธ์จ ์ด๋ค ๊ฐ์๋ ์์กดํ์ง ์์ผ๋ฏ๋ก, ๋ค์ ์คํํ ํ์๊ฐ ์ ํ ์๋ค๋ ๊ฒ์ ์๋ ค์ฃผ๊ฒ ๋ฉ๋๋ค. ์ด๊ฒ์ ํน๋ณํ ๊ฒฝ์ฐ๋ก ๊ฐ์ฃผํ์ง๋ ์๊ณ , ์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ด ํญ์ ์ด๋ป๊ฒ ๋์ํ๋์ง ์ง์ ์ ์ผ๋ก ๋ณด์ฌ์ฃผ๋ ๊ฒ๋ฟ์ ๋๋ค.๋น ๋ฐฐ์ด(
[]
)์ ์ ๋ฌํ๋ค๋ฉด effect ์์ ์๋ props์ state๋ ํญ์ ์ด๊น๊ฐ์ ๊ฐ์ง๊ฒ ๋ ๊ฒ์ ๋๋ค. ๋ ๋ฒ์งธ ์ธ์๋ก์จ[]
์ ์ ๋ฌํ๋ ๊ฒ์ด ์น์ํcomponentDidMount
์componentWillUnmount
์ ์ํ ๊ฐ๋ ๊ณผ ๋น์ทํ๊ฒ ๋๊ปด์ง๊ฒ ์ง๋ง, effect๊ฐ ๋๋ฌด ์์ฃผ ๋ฆฌ๋ ๋๋ง ๋๋ ๊ฒ์ ํผํ๊ธฐ ์ํ ๋ณดํต ๋ ๋์ ํด๊ฒฐ์ฑ ์ด ์์ต๋๋ค. ๋ํ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ชจ๋ ๊ทธ๋ ค์ง ๋๊น์ง React๋useEffect
์ ์ํ์ ์ง์ฐํ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ์์ ์ ์ํ์ด ๋ฌธ์ ๊ฐ ๋์ง๋ ์๋๋ค๋ ๊ฒ์ ์์ง ๋ง์ธ์.
eslint-plugin-react-hooks
ํจํค์ง์exhaustive-deps
๊ท์น์ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค. ๊ทธ๊ฒ์ ์์กด์ฑ์ด ๋ฐ๋ฅด์ง ์๊ฒ ์ ์๋์๋ค๋ฉด ๊ทธ์ ๋ํด ๊ฒฝ๊ณ ํ๊ณ ์์ ํ๋๋ก ์๋ ค์ค๋๋ค.
์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ effect ํจ์์ ์ธ์๋ก ์ ๋ฌ๋์ง๋ ์์ต๋๋ค. ๊ทธ๋ ์ง๋ง ๊ฐ๋ ์ ์ผ๋ก๋, ์ด ๊ธฐ๋ฒ์ effect ํจ์๊ฐ ๋ฌด์์ผ์ง๋ฅผ ํํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. effect ํจ์ ์์์ ์ฐธ์กฐ๋๋ ๋ชจ๋ ๊ฐ์ ์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ ๋๋ฌ๋์ผ ํฉ๋๋ค. ๋์ค์๋ ์ถฉ๋ถํ ๋ฐ์ ๋ ์ปดํ์ผ๋ฌ๊ฐ ์ด ๋ฐฐ์ด์ ์๋์ ์ผ๋ก ์์ฑํ ์ ์์ ๊ฒ์ ๋๋ค.
useContext
This content is out of date.
Read the new React documentation for
useContext
.
const value = useContext(MyContext);
context ๊ฐ์ฒด(React.createContext
์์ ๋ฐํ๋ ๊ฐ)์ ๋ฐ์ ๊ทธ context์ ํ์ฌ ๊ฐ์ ๋ฐํํฉ๋๋ค. context์ ํ์ฌ ๊ฐ์ ํธ๋ฆฌ ์์์ ์ด Hook์ ํธ์ถํ๋ ์ปดํฌ๋ํธ์ ๊ฐ์ฅ ๊ฐ๊น์ด์ ์๋ <MyContext.Provider>
์ value
prop์ ์ํด ๊ฒฐ์ ๋ฉ๋๋ค.
์ปดํฌ๋ํธ์์ ๊ฐ์ฅ ๊ฐ๊น์ด <MyContext.Provider>
๊ฐ ๊ฐฑ์ ๋๋ฉด ์ด Hook์ ๊ทธ MyContext
provider์๊ฒ ์ ๋ฌ๋ ๊ฐ์ฅ ์ต์ ์ context value
๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋๋ฌ๋ฅผ ํธ๋ฆฌ๊ฑฐ ํฉ๋๋ค. ์์ ์ปดํฌ๋ํธ์์ React.memo
๋๋ shouldComponentUpdate
๋ฅผ ์ฌ์ฉํ๋๋ผ๋ useContext
๋ฅผ ์ฌ์ฉํ๊ณ ์๋ ์ปดํฌ๋ํธ ์์ฒด์์๋ถํฐ ๋ค์ ๋ ๋๋ง๋ฉ๋๋ค.
useContext
๋ก ์ ๋ฌํ ์ธ์๋ context ๊ฐ์ฒด ๊ทธ ์์ฒด์ด์ด์ผ ํจ์ ์์ง ๋ง์ธ์.
- ๋ง๋ ์ฌ์ฉ:
useContext(MyContext)
- ํ๋ฆฐ ์ฌ์ฉ:
useContext(MyContext.Consumer)
- ํ๋ฆฐ ์ฌ์ฉ:
useContext(MyContext.Provider)
useContext
๋ฅผ ํธ์ถํ ์ปดํฌ๋ํธ๋ context ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ํญ์ ๋ฆฌ๋ ๋๋ง ๋ ๊ฒ์
๋๋ค. ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ํ๋ ๊ฒ์ ๋น์ฉ์ด ๋ง์ด ๋ ๋ค๋ฉด, ๋ฉ๋ชจ์ด์ ์ด์
์ ์ฌ์ฉํ์ฌ ์ต์ ํํ ์ ์์ต๋๋ค.
ํ
์ฌ๋ฌ๋ถ์ด Hook ๋ณด๋ค context API์ ์น์ํ๋ค๋ฉด
useContext(MyContext)
๋ ํด๋์ค์์์static contextType = MyContext
๋๋<MyContext.Consumer>
์ ๊ฐ๋ค๊ณ ๋ณด๋ฉด ๋ฉ๋๋ค.
useContext(MyContext)
๋ context๋ฅผ ์ฝ๊ณ context์ ๋ณ๊ฒฝ์ ๊ตฌ๋ ํ๋ ๊ฒ๋ง ๊ฐ๋ฅํฉ๋๋ค. context์ ๊ฐ์ ์ค์ ํ๊ธฐ ์ํด์๋ ์ฌ์ ํ ํธ๋ฆฌ์ ์ ๊ณ์ธต์์์<MyContext.Provider>
๊ฐ ํ์ํฉ๋๋ค.
useContext๋ฅผ Context.Provider์ ๊ฐ์ด ์ฌ์ฉํด์ฃผ์ธ์
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> );
}
ํด๋น ์์๋ Context ๊ณ ๊ธ ์๋ด์์์ ์ฌ์ฉํ๋ ์์๊ฐ hook์ผ๋ก ์์ ๋์์ผ๋ฉฐ ์๋ด์์์ Context๋ฅผ ์ธ์ , ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ์์ธํ ์ ์ ์์ต๋๋ค.
์ถ๊ฐ Hook
๋ค์์ Hook๋ ์ด์ ์น์ ์์์ ๊ธฐ๋ณธ Hook์ ๋ณ๊ฒฝ์ด๊ฑฐ๋ ํน์ ํ ๊ฒฝ์ฐ์๋ง ํ์ํ ๊ฒ์ ๋๋ค. ์ตํ๋ ๊ฒ์ ๋๋ฌด ์๋ฐ๋ฐ์ง๋ ๋ง์ธ์.
useReducer
This content is out of date.
Read the new React documentation for
useReducer
.
const [state, dispatch] = useReducer(reducer, initialArg, init);
useState
์ ๋์ฒด ํจ์์
๋๋ค. (state, action) => newState
์ ํํ๋ก reducer๋ฅผ ๋ฐ๊ณ dispatch
๋ฉ์๋์ ์ง์ ํํ๋ก ํ์ฌ state๋ฅผ ๋ฐํํฉ๋๋ค. (Redux์ ์ต์ํ๋ค๋ฉด ์ด๊ฒ์ด ์ด๋ป๊ฒ ๋์ํ๋์ง ์ฌ๋ฌ๋ถ์ ์ด๋ฏธ ์๊ณ ์์ ๊ฒ์
๋๋ค.)
๋ค์์ ํ์๊ฐ์ ํฌํจํ๋ ๋ณต์กํ ์ ์ ๋ก์ง์ ๋ง๋๋ ๊ฒฝ์ฐ๋ ๋ค์ state๊ฐ ์ด์ state์ ์์กด์ ์ธ ๊ฒฝ์ฐ์ ๋ณดํต useState
๋ณด๋ค useReducer
๋ฅผ ์ ํธํฉ๋๋ค. ๋ํ useReducer
๋ ์์ธํ ์
๋ฐ์ดํธ๋ฅผ ํธ๋ฆฌ๊ฑฐ ํ๋ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์๊ฒ ํ๋๋ฐ, ์ด๊ฒ์ ์ฝ๋ฐฑ ๋์ dispatch
๋ฅผ ์ ๋ฌ ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์๋๋ useState
๋ด์ฉ์ ์๋ ์นด์ดํฐ ์์์ธ๋ฐ reducer๋ฅผ ์ฌ์ฉํด์ ๋ค์ ์์ฑํ ๊ฒ์
๋๋ค.
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
์ฃผ์
React๋
dispatch
ํจ์์ ๋์ผ์ฑ์ด ์์ ์ ์ด๊ณ ๋ฆฌ๋ ๋๋ง ์์๋ ๋ณ๊ฒฝ๋์ง ์์ผ๋ฆฌ๋ผ๋ ๊ฒ์ ๋ณด์ฅํฉ๋๋ค. ์ด๊ฒ์ดuseEffect
๋useCallback
์์กด์ฑ ๋ชฉ๋ก์ ์ด ํจ์๋ฅผ ํฌํจํ์ง ์์๋ ๊ด์ฐฎ์ ์ด์ ์ ๋๋ค.
์ด๊ธฐ state์ ๊ตฌ์ฒดํ
useReducer
state์ ์ด๊ธฐํ์๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์ ์ค์ผ์ด์ค์ ๋ฐ๋ผ์ ํ ๊ฐ์ง๋ฅผ ์ ํํ์ธ์. ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ด๊ธฐ state๋ฅผ ๋ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ๋ ๊ฒ์
๋๋ค.
const [state, dispatch] = useReducer(
reducer,
{count: initialCount} );
์ฃผ์
React์์๋ Reducer์ ์ธ์๋ก์จ
state = initialState
์ ๊ฐ์ ์ด๊ธฐ๊ฐ์ ๋ํ๋ด๋, Redux์์๋ ๋ณดํธํ๋ ๊ด์ต์ ์ฌ์ฉํ์ง ์์ต๋๋ค. ๋๋๋ก ์ด๊ธฐ๊ฐ์ props์ ์์กดํ ํ์๊ฐ ์์ด Hook ํธ์ถ์์ ์ง์ ๋๊ธฐ๋ ํฉ๋๋ค. ์ด๊ธฐ๊ฐ์ ๋ํ๋ด๋ ๊ฒ์ด ์ ๋ง ํ์ํ๋ค๋ฉดuseReducer(reducer, undefined, reducer)
๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ผ๋ก Redux๋ฅผ ๋ชจ๋ฐฉํ ์๋ ์๊ฒ ์ง๋ง, ์ด ๋ฐฉ๋ฒ์ ๊ถ์ฅํ์ง๋ ์์ต๋๋ค.
์ด๊ธฐํ ์ง์ฐ
์ด๊ธฐ state๋ฅผ ์กฐ๊ธ ์ง์ฐํด์ ์์ฑํ ์๋ ์์ต๋๋ค. ์ด๋ฅผ ์ํด์๋ init
ํจ์๋ฅผ ์ธ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํฉ๋๋ค. ์ด๊ธฐ state๋ init(initialArg)
์ ์ค์ ๋ ๊ฒ์
๋๋ค.
์ด๊ฒ์ reducer ์ธ๋ถ์์ ์ด๊ธฐ state๋ฅผ ๊ณ์ฐํ๋ ๋ก์ง์ ์ถ์ถํ ์ ์๋๋ก ํฉ๋๋ค. ๋ํ, ์ด๋ค ํ๋์ ๋ํ ๋์์ผ๋ก ๋์ค์ state๋ฅผ ์ฌ์ค์ ํ๋ ๋ฐ์๋ ์ ์ฉํฉ๋๋ค.
function init(initialCount) { return {count: initialCount};}
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
case 'reset': return init(action.payload); default:
throw new Error();
}
}
function Counter({initialCount}) {
const [state, dispatch] = useReducer(reducer, initialCount, init); return (
<>
Count: {state.count}
<button
onClick={() => dispatch({type: 'reset', payload: initialCount})}> Reset
</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
dispatch์ ํํผ
Reducer Hook์์ ํ์ฌ state์ ๊ฐ์ ๊ฐ์ ๋ฐํํ๋ ๊ฒฝ์ฐ React๋ ์์์ ๋ฆฌ๋ ๋๋งํ๊ฑฐ๋ effect๋ฅผ ๋ฐ์ํ์ง ์๊ณ ์ด๊ฒ๋ค์ ํํผํ ๊ฒ์
๋๋ค. (React๋ Object.is
๋น๊ต ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํฉ๋๋ค.)
์คํ์ ํํผํ๊ธฐ ์ ์ React์์ ํน์ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํ๋ ๊ฒ์ด ์ฌ์ ํ ํ์ํ ์๋ ์๋ค๋ ๊ฒ์ ์ฃผ์ํ์ธ์. React๊ฐ ๋ถํ์ํ๊ฒ ํธ๋ฆฌ์ ๊ทธ ์ด์์ผ๋ก ใ๋ ๊น๊ฒใ ๊น์ง๋ ๊ฐ์ง ์์ ๊ฒ์ด๋ฏ๋ก ํฌ๊ฒ ์ ๊ฒฝ ์ฐ์ง ์์ผ์
๋ ๋ฉ๋๋ค. ๋ ๋๋ง ์์ ๊ณ ๋น์ฉ์ ๊ณ์ฐ์ ํ๊ณ ์๋ค๋ฉด useMemo
๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๊ฒ๋ค์ ์ต์ ํํ ์ ์์ต๋๋ค.
useCallback
This content is out of date.
Read the new React documentation for
useCallback
.
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
๋ฉ๋ชจ์ด์ ์ด์ ๋ ์ฝ๋ฐฑ์ ๋ฐํํฉ๋๋ค.
์ธ๋ผ์ธ ์ฝ๋ฐฑ๊ณผ ๊ทธ๊ฒ์ ์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ ์ ๋ฌํ์ธ์. useCallback
์ ์ฝ๋ฐฑ์ ๋ฉ๋ชจ์ด์ ์ด์
๋ ๋ฒ์ ์ ๋ฐํํ ๊ฒ์
๋๋ค. ๊ทธ ๋ฉ๋ชจ์ด์ ์ด์
๋ ๋ฒ์ ์ ์ฝ๋ฐฑ์ ์์กด์ฑ์ด ๋ณ๊ฒฝ๋์์ ๋์๋ง ๋ณ๊ฒฝ๋ฉ๋๋ค. ์ด๊ฒ์, ๋ถํ์ํ ๋ ๋๋ง์ ๋ฐฉ์งํ๊ธฐ ์ํด (์๋ก shouldComponentUpdate
๋ฅผ ์ฌ์ฉํ์ฌ) ์ฐธ์กฐ์ ๋์ผ์ฑ์ ์์กด์ ์ธ ์ต์ ํ๋ ์์ ์ปดํฌ๋ํธ์ ์ฝ๋ฐฑ์ ์ ๋ฌํ ๋ ์ ์ฉํฉ๋๋ค.
useCallback(fn, deps)
์ useMemo(() => fn, deps)
์ ๊ฐ์ต๋๋ค.
์ฃผ์
์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ด ์ฝ๋ฐฑ์ ์ธ์๋ก ์ ๋ฌ๋์ง๋ ์์ต๋๋ค. ๊ทธ๋ ์ง๋ง ๊ฐ๋ ์ ์ผ๋ก๋, ์ด ๊ธฐ๋ฒ์ ์ฝ๋ฐฑ ํจ์๊ฐ ๋ฌด์์ผ์ง๋ฅผ ํํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์ฝ๋ฐฑ ์์์ ์ฐธ์กฐ๋๋ ๋ชจ๋ ๊ฐ์ ์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ ๋ํ๋์ผ ํฉ๋๋ค. ๋์ค์๋ ์ถฉ๋ถํ ๋ฐ์ ๋ ์ปดํ์ผ๋ฌ๊ฐ ์ด ๋ฐฐ์ด์ ์๋์ ์ผ๋ก ์์ฑํ ์ ์์ ๊ฒ์ ๋๋ค.
eslint-plugin-react-hooks
ํจํค์ง์ ์ผ๋ถ๋ก์จexhaustive-deps
๊ท์น์ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค. ๊ทธ๊ฒ์ ์์กด์ฑ์ด ๋ฐ๋ฅด์ง ์๊ฒ ์ ์๋์๋ค๋ฉด ๊ทธ์ ๋ํด ๊ฒฝ๊ณ ํ๊ณ ์์ ํ๋๋ก ์๋ ค์ค๋๋ค.
useMemo
This content is out of date.
Read the new React documentation for
useMemo
.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
๋ฉ๋ชจ์ด์ ์ด์ ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค.
โ์์ฑ(create)โ ํจ์์ ๊ทธ๊ฒ์ ์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ ์ ๋ฌํ์ธ์. useMemo
๋ ์์กด์ฑ์ด ๋ณ๊ฒฝ๋์์ ๋์๋ง ๋ฉ๋ชจ์ด์ ์ด์
๋ ๊ฐ๋ง ๋ค์ ๊ณ์ฐ ํ ๊ฒ์
๋๋ค. ์ด ์ต์ ํ๋ ๋ชจ๋ ๋ ๋๋ง ์์ ๊ณ ๋น์ฉ ๊ณ์ฐ์ ๋ฐฉ์งํ๊ฒ ํด ์ค๋๋ค.
useMemo
๋ก ์ ๋ฌ๋ ํจ์๋ ๋ ๋๋ง ์ค์ ์คํ๋๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์. ํต์์ ์ผ๋ก ๋ ๋๋ง ์ค์๋ ํ์ง ์๋ ๊ฒ์ ์ด ํจ์ ๋ด์์ ํ์ง ๋ง์ธ์. ์๋ฅผ ๋ค์ด, ์ฌ์ด๋ ์ดํํธ(side effects)๋ useEffect
์์ ํ๋ ์ผ์ด์ง useMemo
์์ ํ๋ ์ผ์ด ์๋๋๋ค.
๋ฐฐ์ด์ด ์๋ ๊ฒฝ์ฐ ๋งค ๋ ๋๋ง ๋๋ง๋ค ์ ๊ฐ์ ๊ณ์ฐํ๊ฒ ๋ ๊ฒ์ ๋๋ค.
useMemo
๋ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด ์ฌ์ฉํ ์๋ ์์ง๋ง ์๋ฏธ์์ผ๋ก ๋ณด์ฅ์ด ์๋ค๊ณ ์๊ฐํ์ง๋ ๋ง์ธ์. ๊ฐ๊น์ด ๋ฏธ๋์ React์์๋, ์ด์ ๋ฉ๋ชจ์ด์ ์ด์
๋ ๊ฐ๋ค์ ์ผ๋ถ๋ฅผ โ์์ด๋ฒ๋ฆฌ๊ณ โ ๋ค์ ๋ ๋๋ง ์์ ๊ทธ๊ฒ๋ค์ ์ฌ๊ณ์ฐํ๋ ๋ฐฉํฅ์ ํํ ์ง๋ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด, ์คํ์คํฌ๋ฆฐ ์ปดํฌ๋ํธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๋ ๋ฑ์ด ์์ ์ ์์ต๋๋ค. useMemo
๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ๋์ํ ์ ์๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๊ทธ๊ฒ์ ์ถ๊ฐํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํ์ธ์.
์ฃผ์
์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋์ง๋ ์์ต๋๋ค. ๊ทธ๋ ์ง๋ง ๊ฐ๋ ์ ์ผ๋ก๋, ์ด ๊ธฐ๋ฒ์ ํจ์๊ฐ ๋ฌด์์ผ์ง๋ฅผ ํํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ํจ์ ์์์ ์ฐธ์กฐ๋๋ ๋ชจ๋ ๊ฐ์ ์์กด์ฑ ๊ฐ์ ๋ฐฐ์ด์ ๋ํ๋์ผ ํฉ๋๋ค. ๋์ค์๋ ์ถฉ๋ถํ ๋ฐ์ ๋ ์ปดํ์ผ๋ฌ๊ฐ ์ด ๋ฐฐ์ด์ ์๋์ผ๋ก ์์ฑํ ์ ์์ ๊ฒ์ ๋๋ค.
eslint-plugin-react-hooks
ํจํค์ง์ ์ผ๋ถ๋ก์จexhaustive-deps
๊ท์น์ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค. ๊ทธ๊ฒ์ ์์กด์ฑ์ด ๋ฐ๋ฅด์ง ์๊ฒ ์ ์๋์๋ค๋ฉด ๊ทธ์ ๋ํด ๊ฒฝ๊ณ ํ๊ณ ์์ ํ๋๋ก ์๋ ค์ค๋๋ค.
useRef
This content is out of date.
Read the new React documentation for
useRef
.
const refContainer = useRef(initialValue);
useRef
๋ .current
ํ๋กํผํฐ๋ก ์ ๋ฌ๋ ์ธ์(initialValue
)๋ก ์ด๊ธฐํ๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ref ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ๋ฐํ๋ ๊ฐ์ฒด๋ ์ปดํฌ๋ํธ์ ์ ์์ ์ฃผ๊ธฐ๋ฅผ ํตํด ์ ์ง๋ ๊ฒ์
๋๋ค.
์ผ๋ฐ์ ์ธ ์ ์ค์ผ์ด์ค๋ ์์์๊ฒ ๋ช ๋ น์ ์ผ๋ก ์ ๊ทผํ๋ ๊ฒฝ์ฐ์ ๋๋ค.
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
๋ณธ์ง์ ์ผ๋ก useRef
๋ .current
ํ๋กํผํฐ์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ฐ์ ๋ด๊ณ ์๋ โ์์โ์ ๊ฐ์ต๋๋ค.
์๋ง๋ ์ฌ๋ฌ๋ถ์ DOM์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ผ๋ก refs์ ์น์ํ ์ง๋ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. <div ref={myRef} />
๋ฅผ ์ฌ์ฉํ์ฌ React๋ก ref ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค๋ฉด, React๋ ๋
ธ๋๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๋ณ๊ฒฝ๋ DOM ๋
ธ๋์ ๊ทธ๊ฒ์ .current
ํ๋กํผํฐ๋ฅผ ์ค์ ํ ๊ฒ์
๋๋ค.
๊ทธ๋ ์ง๋ง, ref
์์ฑ๋ณด๋ค useRef()
๊ฐ ๋ ์ ์ฉํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ํด๋์ค์์ ์ธ์คํด์ค ํ๋๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์ ์ฌํ ์ด๋ค ๊ฐ๋ณ๊ฐ์ ์ ์งํ๋ ๋ฐ์ ํธ๋ฆฌํฉ๋๋ค.
์ด๊ฒ์ useRef()
๊ฐ ์์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์
๋๋ค. useRef()
์ {current: ...}
๊ฐ์ฒด ์์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ ์ผํ ์ฐจ์ด์ ์ด๋ผ๋ฉด useRef
๋ ๋งค๋ฒ ๋ ๋๋ง์ ํ ๋ ๋์ผํ ref ๊ฐ์ฒด๋ฅผ ์ ๊ณตํ๋ค๋ ๊ฒ์
๋๋ค.
useRef
๋ ๋ด์ฉ์ด ๋ณ๊ฒฝ๋ ๋ ๊ทธ๊ฒ์ ์๋ ค์ฃผ์ง๋ ์๋๋ค๋ ๊ฒ์ ์ ๋
ํ์ธ์. .current
ํ๋กํผํฐ๋ฅผ ๋ณํํ๋ ๊ฒ์ด ๋ฆฌ๋ ๋๋ง์ ๋ฐ์์ํค์ง๋ ์์ต๋๋ค. React๊ฐ DOM ๋
ธ๋์ ref๋ฅผ attachํ๊ฑฐ๋ detachํ ๋ ์ด๋ค ์ฝ๋๋ฅผ ์คํํ๊ณ ์ถ๋ค๋ฉด ๋์ ์ฝ๋ฐฑ ref๋ฅผ ์ฌ์ฉํ์ธ์.
useImperativeHandle
This content is out of date.
Read the new React documentation for
useImperativeHandle
.
useImperativeHandle(ref, createHandle, [deps])
useImperativeHandle
์ ref
๋ฅผ ์ฌ์ฉํ ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ๋
ธ์ถ๋๋ ์ธ์คํด์ค ๊ฐ์ ์ฌ์ฉ์ํ(customizes)ํฉ๋๋ค. ํญ์ ๊ทธ๋ ๋ฏ์ด, ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ref๋ฅผ ์ฌ์ฉํ ๋ช
๋ นํ ์ฝ๋๋ ํผํด์ผ ํฉ๋๋ค. useImperativeHandle
๋ forwardRef
์ ๋๋ถ์ด ์ฌ์ฉํ์ธ์.
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
์์ ์์์์ <FancyInput ref={inputRef} />
๋ฅผ ๋ ๋๋งํ ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ inputRef.current.focus()
๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
useLayoutEffect
This content is out of date.
Read the new React documentation for
useLayoutEffect
.
์ด ํจ์์ ์๊ทธ๋์ฒ๋ useEffect
์ ๋์ผํ๊ธด ํ๋ฐ, ๋ชจ๋ DOM ๋ณ๊ฒฝ ํ์ ๋๊ธฐ์ ์ผ๋ก ๋ฐ์ํฉ๋๋ค. ์ด๊ฒ์ DOM์์ ๋ ์ด์์์ ์ฝ๊ณ ๋๊ธฐ์ ์ผ๋ก ๋ฆฌ๋ ๋๋งํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉํ์ธ์. useLayoutEffect
์ ๋ด๋ถ์ ์์ ๋ ๊ฐฑ์ ์ ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ ๊ทธ๋ฆฌ๊ธฐ ์ด์ ์์ ์ ๋๊ธฐ์ ์ผ๋ก ์ํ๋ ๊ฒ์
๋๋ค.
ํ๋ฉด ๊ฐฑ์ ์ฐจ๋จ์ ๋ฐฉ์ง๊ฐ ๊ฐ๋ฅํ ๋ ํ์ค useEffect
๋ฅผ ๋จผ์ ์ฌ์ฉํ์ธ์.
ํ
ํด๋์ค ์ปดํฌ๋ํธ์์ ์ฝ๋๋ฅผ ๋ณํํ๋ ๊ฒฝ์ฐ์
useLayoutEffect
๋componentDidMount
๋componentDidUpdate
์ ๋์ผํ ๋จ๊ณ๋ฅผ ์คํํ๊ฒ ๋๋ค๋ ๊ฒ์ ์ฃผ์ํ๊ธฐ ๋ฐ๋๋๋ค. ๊ทธ๋ ๊ธฐ๋ ํ์ง๋ง, ๋จผ์ useEffect
๋ฅผ ์ฌ์ฉํด ๋ณด๊ณ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ๊ทธ๋ค์์ผ๋กuseLayoutEffect
๋ฅผ ์ฌ์ฉํด ๋ณด๊ธฐ๋ฅผ ๊ถํฉ๋๋ค.์๋ฒ ๋ ๋๋ง์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ผ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋ชจ๋ ๋ค์ด๋ก๋๋ ๋๊น์ง๋
useLayoutEffect
์useEffect
์ด๋ ๊ฒ๋ ์คํ๋์ง ์๋๋ค๋ ๊ฒ์ ๋ช ์ฌํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ด ์๋ฒ์์ ๋ ๋๋ง ๋๋ ์ปดํฌ๋ํธ์์useLayoutEffect
๊ฐ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ์ ๋ํด React๊ฐ ๊ฒฝ๊ณ ํ๋ ์ด์ ์ ๋๋ค. ์ด๋ฅผ ์์ ํ๊ธฐ ์ํด์๋ (์ต์ด ๋ ๋๋ง ์์ ํ์ํ์ง ์๋ค๋ฉด) ๋ก์ง์useEffect
๋ก ์ด๋ํ๋ค๊ฑฐ๋ (useLayoutEffect
๊ฐ ์ํ๋ ๋๊น์ง HTML์ด ๊นจ์ ธ ๋ณด์ด๋ ๊ฒฝ์ฐ๋) ํด๋ผ์ด์ธํธ ๋ ๋๋ง์ด ์๋ฃ๋ ๋๊น์ง ์ปดํฌ๋ํธ ๋ ธ์ถ์ ์ง์ฐํ๋๋ก ํ์ธ์.์๋ฒ์์ ๋ ๋๋ง๋ HTML์์ ๋ ์ด์์ effect๊ฐ ํ์ํ ์ปดํฌ๋ํธ๋ฅผ ๋ฐฐ์ ํ๊ณ ์ถ๋ค๋ฉด,
showChild && <Child />
๋ฅผ ์ฌ์ฉํ์ฌ ์กฐ๊ฑด์ ์ผ๋ก ๋ ๋๋ง ํ๊ณuseEffect(() => { setShowChild(true); }, [])
๋ฅผ ์ฌ์ฉํ์ฌ ๋ ธ์ถ์ ์ง์ฐ์ํค์ธ์. ์ด๋ฐ ๋ฐฉ๋ฒ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์ฃผ์ ๋๊ธฐ ์ ์ ๊นจ์ ธ ๋ณด์ผ ์ ์๋ UI๋ ํํ๋์ง ์๊ฒ ๋ฉ๋๋ค.
useDebugValue
This content is out of date.
Read the new React documentation for
useDebugValue
.
useDebugValue(value)
useDebugValue
๋ React ๊ฐ๋ฐ์๋๊ตฌ์์ ์ฌ์ฉ์ Hook ๋ ์ด๋ธ์ ํ์ํ๋ ๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, โ๋๋ง์ Hook ๋ง๋ค๊ธฐโ์ ์ค๋ช
ํ๊ณ ์๋ useFriendStatus
์ฌ์ฉ์ Hook์ ๋ํด์ ์๊ฐํด ๋ด
์๋ค.
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
// ...
// Show a label in DevTools next to this Hook // e.g. "FriendStatus: Online" useDebugValue(isOnline ? 'Online' : 'Offline');
return isOnline;
}
ํ
๋ชจ๋ ์ฌ์ฉ์ Hook์ ๋๋ฒ๊ทธ ๊ฐ์ ์ถ๊ฐํ๊ธฐ๋ฅผ ๊ถํ์ง๋ ์์ต๋๋ค. ์ด๊ฒ์ ์ฌ์ฉ์ Hook์ด ๊ณต์ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ถ์ผ ๋ ๊ฐ์ฅ ์ ์ฉํฉ๋๋ค.
๋๋ฒ๊ทธ ๊ฐ ํฌ๋งทํ ์ง์ฐํ๊ธฐ
๊ฒฝ์ฐ์ ๋ฐ๋ผ ๋์คํ๋ ์ด ๊ฐ์ ํฌ๋งทํ ํ๋ ๊ฒ์ด ๊ณ ๋น์ฉ์ ์ฐ์ฐ์ผ ์ ์์ต๋๋ค. ๋ํ, ์ฌ์ค์ Hook์ด ๊ฐ์ง๋์ง ์๋๋ค๋ฉด ๋ถํ์ํ๊ธฐ๋ ํฉ๋๋ค.
์ด๋ฐ ์ด์ ๋ก useDebugValue
๋ ์ต์
๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ํฌ๋งทํ
ํจ์๋ฅผ ์ ๋ฌํ ์๋ ์์ต๋๋ค. ์ด ํจ์๋ Hook๊ฐ ๊ฐ์ง๋์์ ๋๋ง ํธ์ถ๋ฉ๋๋ค. ์ด๊ฒ์ ํ๋ผ๋ฏธํฐ๋ก์จ ๋๋ฒ๊ทธ ๊ฐ์ ์ ๋ฌ๋ฐ์ ํฌ๋งท๋ ๋
ธ์ถ๊ฐ์ ๋ฐํํด์ผ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ฌ์ฉ์ Hook์ ๋ค์์ ํฌ๋งท ํ์์ ์ฌ์ฉํด์ toDateString
ํจ์๋ฅผ ๋ถํ์ํ๊ฒ ํธ์ถํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
useDebugValue(date, date => date.toDateString());
useDeferredValue
This content is out of date.
Read the new React documentation for
useDeferredValue
.
const deferredValue = useDeferredValue(value);
useDeferredValue
accepts a value and returns a new copy of the value that will defer to more urgent updates. If the current render is the result of an urgent update, like user input, React will return the previous value and then render the new value after the urgent render has completed.
This hook is similar to user-space hooks which use debouncing or throttling to defer updates. The benefits to using useDeferredValue
is that React will work on the update as soon as other work finishes (instead of waiting for an arbitrary amount of time), and like startTransition
, deferred values can suspend without triggering an unexpected fallback for existing content.
Memoizing deferred children
useDeferredValue
only defers the value that you pass to it. If you want to prevent a child component from re-rendering during an urgent update, you must also memoize that component with React.memo
or React.useMemo
:
function Typeahead() {
const query = useSearchQuery('');
const deferredQuery = useDeferredValue(query);
// Memoizing tells React to only re-render when deferredQuery changes,
// not when query changes.
const suggestions = useMemo(() =>
<SearchSuggestions query={deferredQuery} />,
[deferredQuery]
);
return (
<>
<SearchInput query={query} />
<Suspense fallback="Loading results...">
{suggestions}
</Suspense>
</>
);
}
Memoizing the children tells React that it only needs to re-render them when deferredQuery
changes and not when query
changes. This caveat is not unique to useDeferredValue
, and itโs the same pattern you would use with similar hooks that use debouncing or throttling.
useTransition
This content is out of date.
Read the new React documentation for
useTransition
.
const [isPending, startTransition] = useTransition();
Returns a stateful value for the pending state of the transition, and a function to start it.
startTransition
lets you mark updates in the provided callback as transitions:
startTransition(() => {
setCount(count + 1);
});
isPending
indicates when a transition is active to show a pending state:
function App() {
const [isPending, startTransition] = useTransition();
const [count, setCount] = useState(0);
function handleClick() {
startTransition(() => {
setCount(c => c + 1);
});
}
return (
<div>
{isPending && <Spinner />}
<button onClick={handleClick}>{count}</button>
</div>
);
}
Note:
Updates in a transition yield to more urgent updates such as clicks.
Updates in a transitions will not show a fallback for re-suspended content. This allows the user to continue interacting with the current content while rendering the update.
useId
This content is out of date.
Read the new React documentation for
useId
.
const id = useId();
useId
is a hook for generating unique IDs that are stable across the server and client, while avoiding hydration mismatches.
Note
useId
is not for generating keys in a list. Keys should be generated from your data.
For a basic example, pass the id
directly to the elements that need it:
function Checkbox() {
const id = useId();
return (
<>
<label htmlFor={id}>Do you like React?</label>
<input id={id} type="checkbox" name="react"/>
</>
);
};
For multiple IDs in the same component, append a suffix using the same id
:
function NameFields() {
const id = useId();
return (
<div>
<label htmlFor={id + '-firstName'}>First Name</label>
<div>
<input id={id + '-firstName'} type="text" />
</div>
<label htmlFor={id + '-lastName'}>Last Name</label>
<div>
<input id={id + '-lastName'} type="text" />
</div>
</div>
);
}
Note:
useId
generates a string that includes the:
token. This helps ensure that the token is unique, but is not supported in CSS selectors or APIs likequerySelectorAll
.
useId
supports anidentifierPrefix
to prevent collisions in multi-root apps. To configure, see the options forhydrateRoot
andReactDOMServer
.
Library Hooks
The following Hooks are provided for library authors to integrate libraries deeply into the React model, and are not typically used in application code.
useSyncExternalStore
This content is out of date.
Read the new React documentation for
useSyncExternalStore
.
const state = useSyncExternalStore(subscribe, getSnapshot[, getServerSnapshot]);
useSyncExternalStore
is a hook recommended for reading and subscribing from external data sources in a way thatโs compatible with concurrent rendering features like selective hydration and time slicing.
This method returns the value of the store and accepts three arguments:
subscribe
: function to register a callback that is called whenever the store changes.getSnapshot
: function that returns the current value of the store.getServerSnapshot
: function that returns the snapshot used during server rendering.
The most basic example simply subscribes to the entire store:
const state = useSyncExternalStore(store.subscribe, store.getSnapshot);
However, you can also subscribe to a specific field:
const selectedField = useSyncExternalStore(
store.subscribe,
() => store.getSnapshot().selectedField,
);
When server rendering, you must serialize the store value used on the server, and provide it to useSyncExternalStore
. React will use this snapshot during hydration to prevent server mismatches:
const selectedField = useSyncExternalStore(
store.subscribe,
() => store.getSnapshot().selectedField,
() => INITIAL_SERVER_SNAPSHOT.selectedField,
);
Note:
getSnapshot
must return a cached value. If getSnapshot is called multiple times in a row, it must return the same exact value unless there was a store update in between.A shim is provided for supporting multiple React versions published as
use-sync-external-store/shim
. This shim will preferuseSyncExternalStore
when available, and fallback to a user-space implementation when itโs not.As a convenience, we also provide a version of the API with automatic support for memoizing the result of getSnapshot published as
use-sync-external-store/with-selector
.
useInsertionEffect
This content is out of date.
Read the new React documentation for
useInsertionEffect
.
useInsertionEffect(didUpdate);
The signature is identical to useEffect
, but it fires synchronously before all DOM mutations. Use this to inject styles into the DOM before reading layout in useLayoutEffect
. Since this hook is limited in scope, this hook does not have access to refs and cannot schedule updates.
Note:
useInsertionEffect
should be limited to css-in-js library authors. PreferuseEffect
oruseLayoutEffect
instead.