-
[React] ํจ์ํ ์ปดํฌ๋ํธ์ React hooksReact 2020. 6. 23. 20:17
๐ Hook์ ๊ฐ์
Hook๊ฐ React ๋ฒ์ 16.8์ ์๋กญ๊ฒ ์ถ๊ฐ๋์๋ค. Hook๋ฅผ ์ด์ฉํ์ฌ Class๋ฅผ ์์ฑํ ํ์ ์์ด ์ํ ๊ฐ๊ณผ ์ฌ๋ฌ React์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค.
๐ธ Hook๋ฅผ ๋ง๋ค๊ฒ ๋ ๋๊ธฐ
- ์ปดํฌ๋ํธ ์ฌ์ด์์ ์ํ์ ๊ด๋ จ๋ ๋ก์ง์ ์ฌ์ฌ์ฉํ๊ธฐ ์ด๋ ต๋ค.
- ๋ณต์กํ ์ปดํฌ๋ํธ๋ค์ ์ดํดํ๊ธฐ ์ด๋ ต๋ค.
- Class์ ์ฌ๋๊ณผ ๊ธฐ๊ณ๋ฅผ ํผ๋์ํจ๋ค.
๐ Hook์ ๊ท์น
Hook์ ์ฌ์ฉํ ๋๋ ๋ ๊ฐ์ง ๊ท์น์ ์ค์ํด์ผ ํ๋ค.
์ด๋ฌํ ๊ท์น์ ์๋์ผ๋ก ์ง์ผ์ฃผ๋ linter ํ๋ฌ๊ทธ์ธ์ด ์๋ค.
์ ESLint ํ๋ฌ๊ทธ์ธ์ create react app์ ๊ธฐ๋ณธ์ ์ผ๋ก ํฌํจํ๊ณ ์๋ค.- 1. ์ต์์์์๋ง Hook์ ํธ์ถํด์ผ ํ๋ค.
๋ฐ๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ ํน์ ์ค์ฒฉ๋ ํจ์ ๋ด์์ Hook์ ํธ์ถํ์ง ์๋๋ค. - 2. ์ค์ง React ํจ์ ๋ด์์ Hook์ ํธ์ถํด์ผ ํ๋ค.
Hook์ ์ผ๋ฐ์ ์ธ javascript ํจ์์์ ํธ์ถํ์ง ๋ง์์ผ ํ๋ค.
๐ useState
-
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ Hook๋ก ํจ์ํ ์ปดํฌ๋ํธ์์ ๊ฐ๋ณ์ ์ธ ์ํ๋ฅผ ์ง๋ ์ ์๊ฒ ํด ์ค๋ค.
-
useState
ํจ์์ ํ๋ผ๋ฏธํฐ์๋ ์ํ์ ๊ธฐ๋ณธ๊ฐ์ ๋ฃ์ด์ฃผ๋ ๊ฒ์ผ๋ก ์ด๊ธฐ ๋ ๋๋ง ์์ ์ฌ์ฉํ๋ ๊ฐ์ด๋ค. -
๊ทธ ์ดํ์ ๋ ๋๋ง ์์๋ ์ด ๊ฐ์ ๋ฌด์๋๋ค.
const [value,setValue] = useState(0);
-
useState
ํจ์๋ ํธ์ถ๋๋ฉด ๋ฐฐ์ด์ ๋ฐํํ๋๋ฐ ๋ฐฐ์ด์ ์ฒซ ๋ฒ์งธ ์์๋ ์ํ ๊ฐ, ๋ ๋ฒ์งธ ์์๋ ์ํ๋ฅผ ์ค์ ํ๋ ํจ์์ด๋ค. -
setValue
ํจ์๋value
๋ฅผ ๊ฐฑ์ ํ ๋ ์ฌ์ฉํ๋ค.setValue(newValue);
-
ํด๋์ค ์ปดํฌ๋ํธ
class Example extends React.Component { constructor(props) { super(props); this.state = { value: 0 }; } render() { return ( <div> <p> ์นด์ดํฐ ๊ฐ {this.state.value} ์ ๋๋ค. </p> <button onClick={() => this.setState({ count: this.state.value + 1 })}>+1</button> <button onClick={() => this.setState({ count: this.state.value - 1 })}>-1</button> </div> ); } }
-
ํจ์ํ ์ปดํฌ๋ํธ
const Counter = () => { const [value,setValue] = useState(0); return( <div> <p> ์นด์ดํฐ ๊ฐ์ <b>{value}</b>์ ๋๋ค. </p> <button onClick={() => setValue(value+1)}>+1</button> <button onClick={() => setValue(value-1)}>-1</button> </div> )
-
๐ธ state ๊ฐฑ์ ์ ์ทจ์
State Hook์ ํ์ฌ์ state์ ๋์ผํ ๊ฐ์ผ๋ก ๊ฐฑ์ ํ๋ ๊ฒฝ์ฐ React๋ ์์์ ๋ ๋๋ง ํ๋ค๊ฑฐ๋ ๋ฌด์์ ์คํํ๋ ๊ฒ์ ํํผํ๊ณ ๊ทธ ์ฒ๋ฆฌ๋ฅผ ์ข ๋ฃํ๋ค.(React๋ Object.is ๋น๊ต ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ค.)
๐ useEffect
-
useEffect
์ ์ ๋ฌ๋ ํจ์๋ ํ๋ฉด์ ๋ ๋๋ง์ด ์๋ฃ๋ ํ์ ์ํ๋๊ฒ ๋๋ค. -
๋ฆฌ์กํธ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ๋๋ง๋ค ํน์ ์์ ์ ์ํํ๋๋ก ์ค์ ํ ์ ์๋ Hook์ด๋ค.
-
ํด๋์คํ ์ปดํฌ๋ํธ์
componentDidMount
์componentDidUpdate
๋ฅผ ํฉ์น ํํ๋ ๊ฐ๋ค. -
useEffect()
๋ ๊ฐ์ด ์ ๋ฐ์ดํธ๋ ๋๋ง๋ค ์คํ๋๋๋ฐ ํ๋ฉด์ ๋งจ ์ฒ์ ๋ ๋๋ง ๋ ๋๋ง ์คํํ๊ณ , ์ ๋ฐ์ดํธ๋ ๋๋ ์คํ๋์ง ์๊ฒ ํ๋ ค๋ฉด ํจ์์ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ๋น์ด ์๋ ๋ฐฐ์ด์ ๋ฃ์ด ์ฃผ๋ฉด ๋๋ค. -
์ด ๋ฐฐ์ด์ effect๊ฐ ์ข ์๋์ด ์๋ ๊ฐ์ ๋ฐฐ์ด์ด์ง๋ง, ๋น ๋ฐฐ์ด ์์ ์ด๋ค ๊ฐ์๋ ์์กดํ์ง ์์ผ๋ฏ๋ก, ๋ค์ ์คํํ ํ์๊ฐ ์ ํ ์์ด์ง๋ค.
useEffect(() => { console.log({ name, nickName }) },[])
-
ํน์ ๊ฐ์ด ์ ๋ฐ์ดํธ๋ ๋๋ง ์คํํ๊ณ ์ถ์ผ๋ฉด ๋ ๋ฒ์งธ ํ๋ฆฌ๋ฏธํฐ๋ก ์ ๋ฌ๋๋ ๋ฐฐ์ด ์์ ๊ฒ์ฌํ๊ณ ์ถ์ ๊ฐ์ ๋ฃ์ด ์ฃผ๋ฉด ๋๋ค.
useEffect(() => { console.log(name); },[name])
๐ธ effect ์ ๋ฆฌ
-
์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋๊ธฐ ์ ์ด๋ ์ ๋ฐ์ดํธ๋๊ธฐ ์ง์ ์ ์ด๋ค ์์ ์ ์ํํ๊ณ ์ถ๋ค๋ฉด
useEffect
์์ ์ ๋ฆฌ(clean-up) ํจ์๋ฅผ ๋ฐํํด ์ฃผ์ด์ผ ํ๋ค. -
์ ๋ฆฌ ํจ์๋ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฉ์ง๋ฅผ ์ํด UI์์ ์ปดํฌ๋ํธ๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ ์ ์ํ๋๋ค.
-
๋ง์ฝ ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ฌ ๋ฒ ๋ ๋๋ง ๋๋ค๋ฉด ๋ค์ effect๊ฐ ์ํ๋๊ธฐ ์ ์ ์ด์ effect๋ ์ ๋ฆฌ๋๋ค.
useEffect(() => { console.log("effect"); console.log({ name, nickName }) return () =>{ console.log('cleanUp'); console.log(name); } },[])
-
์ ๋ฆฌ ํจ์๊ฐ ํธ์ถ๋ ๋๋ ์ ๋ฐ์ดํธ๋๊ธฐ ์ง์ ๊ฐ์ ๋ณด์ฌ์ค๋ค.
๐ useContext
-
๐ React context ์ฐธ๊ณ
const value = useContext(MyContext);
-
context ๊ฐ์ฒด(React.createContext์์ ๋ฐํ๋ ๊ฐ)๋ฅผ ๋ฐ์ ๊ทธ context์ ํ์ฌ ๊ฐ์ ๋ฐํํ๋ค.
-
์ปดํฌ๋ํธ์์ ๊ฐ์ฅ ๊ฐ๊น์ด
<MyContext.Provider>
๊ฐ ๊ฐฑ์ ๋๋ฉด ์ด Hook์ ๊ทธ MyContext.Provider์๊ฒ ์ ๋ฌ๋ ๊ฐ์ฅ ์ต์ ์ context value๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋๋ฌ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋ค. -
useContext
๋ก ์ ๋ฌ๋ ์ธ์๋ context ๊ฐ์ฒด ๊ทธ ์์ฒด์ด์ด์ผ ํ๋ค. -
useContext
๋ฅผ ํธ์ถํ ์ปดํฌ๋ํธ๋ context ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ํญ์ ๋ฆฌ๋ ๋๋ง ๋๋ค. ๋ง์ฝ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋ง ํ๋ ๊ฒ์ ๋ณต์กํด์ง๋ค๋ฉด, ๋ฉ๋ชจ์ด์ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ต์ ํํ ์ ์๋ค.const themes = { light: { foreground: "#000000", background: "#eeeeee" }, dark: { foreground: "#ffffff", background: "#222222" } }; const ThemeContext = React.createContext(themes.light); function App() { return ( // Provider๋ก prop์ ๋ฐ์์ ์ด ๊ฐ์ ํ์์ ์๋ ์ปดํฌ๋ํธ์๊ฒ ์ ๋ฌํ๋ค. (context์ ๋ณํ๋ฅผ ์๋ฆฐ๋ค.) <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 }}>test</button> ); }
๐ useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);
-
useState
์ ๋์ฒด ํจ์๋ก (state, action) => newState์ ํํ๋ก reducer๋ฅผ ๋ฐ๊ณ dispatch ๋ฉ์๋์ ์ง์ ํํ๋ก ํ์ฌ state๋ฅผ ๋ฐํํ๋ค. -
๋ฆฌ๋์๋ ํ์ฌ ์ํ, ๊ทธ๋ฆฌ๊ณ ์ ๋ฐ์ดํธ๋ฅผ ์ํด ํ์ํ ์ ๋ณด๋ฅผ ๋ด์ ์ก์ ๊ฐ์ ์ ๋ฌ๋ฐ์ ์๋ก์ด ์ํ๋ฅผ ๋ฐํํ๋ ํจ์์ด๋ค.
-
๋ฆฌ๋์ ํจ์์์ ์๋ก์ด ์ํ๋ฅผ ๋ง๋ค ๋๋ ๋ถ๋ณ์ฑ์ ์ง์ผ์ผ ํ๋ค.
-
useReducer๋ ์ฝ๋ฐฑ ๋์
dispatch
๋ฅผ ์ ๋ฌํ ์ ์๊ธฐ ๋๋ฌธ์ ์ ๋ฐ์ดํธ๋ฅผ ํ๋ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์๋ค.const initialState = {value : 0}; function reducer(state,action){ switch (action.type){ case 'INCREMENT': return {value : state.value + 1}; case 'DECREMENT': return {value : state.value - 1}; default : //์๋ฌด๊ฒ๋ ํด๋น๋์ง ์์ ๋ ๊ธฐ์กด ์ํ ๋ฐํ return state; } } const Counter = () => { // useReducer(๋ฆฌ๋์ ํจ์, ์ด๊ธฐ๊ฐ) const [state, dispatch] = useReducer(reducer,initialState); return ( <div> <p> ํ์ฌ ์นด์ดํฐ ๊ฐ์ <b>{state.value}</b>์ ๋๋ค. </p> <button onClick={() => dispatch({type : 'INCREMENT'})}>+1</button> <button onClick={() => dispatch({type : 'DECREMENT'})}>-1</button> </div> ); };
-
state
๊ฐ๊ณผdispatch
ํจ์๋ฅผ ๋ฐ์์ค๋๋ฐstate
๋ ํ์ฌ ๊ฐ๋ฆฌํค๊ณ ์๋ ์ํ์ด๊ณ ,dispatch
๋ ์ก์ ์ ๋ฐ์ ํค๊ธฐ๋ ํจ์์ด๋ค. -
useReducer
๋ฅผ ์ฌ์ฉํ์ ๋ ๊ฐ์ฅ ํฐ ์ฅ์ ์ ์ปดํฌ๋ํธ ์ ๋ฐ์ดํธ ๋ก์ง์ ์ปดํฌ๋ํธ ๋ฐ๊นฅ์ผ๋ก ๋นผ๋ผ ์ ์๋ค๋ ์ ์ด๋ค.
๐ธ ์ด๊ธฐํ ์ง์ฐ
-
์ด๊ธฐํ state๋ฅผ ์ง์ฐ์์ผ์ ์์ฑํ ์ ์๋ค.
-
useReducer(๋ฆฌ๋์ ํจ์, ์ด๊ธฐ๊ฐ, init ํจ์) ์ธ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ๋ค.
-
์๋ฅผ ๋ค์ด ๋ฒํผ ํด๋ฆญ ์์ 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: state; } } 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> </> ); }
๐ useMemo
-
useMemo
๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ํ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๋ฐ์ํ๋ ์ฐ์ฐ์ ์ต์ ํํ ์ ์๋ค. -
๋ฉ๋ชจ์ด์ ์ด์ ๋ ๊ฐ์ ๋ฐํํ๋ค.
-
๋ ๋๋ง ํ๋ ๊ณผ์ ์์ ํน์ ๊ฐ์ด ๋ฐ๋์์ ๋๋ง ์ฐ์ฐ์ ์คํํ๊ณ , ์ํ๋ ๊ฐ์ด ๋ฐ๋์ง ์์๋ค๋ฉด ์ด์ ์ ์ฐ์ฐํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ฌ์ฉํ๋ ๋ฐฉ์์ด๋ค.
-
useMemo๋ก ์ ๋ฌ๋ ํจ์๋ ๋ ๋๋ง ์ค์ ์คํ๋๋ค. ๋๋ฌธ์ ๋ ๋๋ง ์ค์ ์คํ๋์ง ์๋ ๊ฒ์ ์ฌ์ฉํ๋ฉด ์ ๋๋ค.
const getAverage = numbers => { console.log("ํ๊ท ๊ฐ ๊ณ์ฐ"); if(numbers.length === 0)return 0; const sum = numbers.reduce((a,b) => a+b); return sum / numbers.length; } // ์๋ต.. const avg = useMemo(() => getAverage(list), [list]); // list ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง ์คํ // ์๋ต..
๐ useCallback
-
useMemo
์ ๋น์ทํ๊ณ ๋ ๋๋ง ์ฑ๋ฅ์ ์ต์ ํํด์ผ ํ๋ ์ํฉ์์ ์ฌ์ฉ๋๋ค. -
๋ฉ๋ชจ์ด์ ์ด์ ๋ ์ฝ๋ฐฑ์ ๋ฐํํ๋ค.
-
์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ ํ์ํ ๋๋ง ์์ฑํ ์ ์๋ค.
-
useCallback(fn, deps)์ useMemo(() => fn, deps)์ ๊ฐ๋ค.
const onChange = useCallback(e => { setNumber(e.target.value); },[]); //์ฒ์ ๋๋๋ง๋ ๋๋ง ํจ์ ์์ฑ const onInsert = useCallback(e => { const nextList = list.concat(parseInt(number)); setList(nextList); setNumber(''); },[number,list]); //number, list ๊ฐ ๋ฐ๋์์ ๋๋ง ํจ์ ์์ฑ
-
useCallback
์ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์๋ ์์ฑํ๊ณ ์ถ์ ํจ์๋ฅผ ๋ฃ๊ณ , ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์๋ ์ด๋ค ๊ฐ์ด ๋ฐ๋์์ ๋ ํจ์๋ฅผ ์๋ก ์์ฑํด์ผ ํ๋์ง๋ฅผ ๋ช ์ํ๋ ๋ฐฐ์ด์ ๋ฃ๋๋ค. -
๋น ๋ฐฐ์ด์ ๋ฃ๊ฒ ๋๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ๋ ๋จ ํ ๋ฒ๋ง ํจ์๊ฐ ์์ฑ๋๊ณ , ๋ฐฐ์ด ์์ ๊ฐ์ ๋ฃ๊ฒ ๋๋ฉด ๋ด์ฉ์ผ ๋ฐ๋๊ฑฐ๋ ์๋ก์ด ํญ๋ชฉ์ด ์ถ๊ฐ๋ ๋๋ง๋ค ํจ์๊ฐ ์์ฑ๋๋ค.
๐ useRef
-
ํจ์ํ ์ปดํฌ๋ํธ์์
ref
๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ํด์ค๋ค.function TextInputWithFocusButton() { const inputEl = useRef(null); //ref ๊ฐ ๊ธฐ๋ณธ๊ฐ ์ค์ const onButtonClick = () => { inputEl.current.focus(); // ๋ฑ๋ก๋ฒํผ ๋๋ฅธ๋ค input ํ๊ทธ focus }; return ( <> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>ํด๋ฆญ</button> </> ); }
-
useRef
๋ฅผ ์ฌ์ฉํ์ฌref
๋ฅผ ์ค์ ํ๋ฉดuseRef
๋ฅผ ํตํด ๋ง๋ ๊ฐ์ฒด ์์current
๊ฐ์ด ์ค์ ์๋ฆฌ๋จผํธ๋ฅผ ๊ฐ๋ฆฌํจ๋ค. -
ref
์์ ๊ฐ์ด ๋ฐ๋์ด๋ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋์ง ์๋๋ค.(๋ ๋๋ง๊ณผ ๊ด๋ จ๋์ง ์์ ๊ฐ์ ๊ด๋ฆฌํ ๋๋ง ์ฌ์ฉ)
๐ useImperativeHandle
useImperativeHandle(ref, createHandle, [deps])
- useImperativeHandle์ 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
- ์ด ํจ์๋ ๋ชจ๋ DOM ๋ณ๊ฒฝ ํ์ ๋๊ธฐ์ ์ผ๋ก ๋ฐ์ํ๊ณ DOM์์ ๋ ์ด์์์ ์ฝ๊ณ ๋๊ธฐ์ ์ผ๋ก ๋ฆฌ๋ ๋๋งํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.
- useLayoutEffect์ ๋ด๋ถ์ ์์ ๋ ๊ฐฑ์ ์ ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ ๊ทธ๋ฆฌ๊ธฐ ์ด์ ์์ ์ ๋๊ธฐ์ ์ผ๋ก ์ํ๋๋ค.
- useLayoutEffect๋ componentDidMount๋ componentDidUpdate์ ๋์ผํ ๋จ๊ณ๋ฅผ ์คํํ๊ธด ํ์ง๋ง ๋จผ์ useEffect๋ฅผ ์ฌ์ฉํ๊ณ ๋ฌธ์ ๊ฐ ์์ผ๋ฉด useLayoutEffect์ ์ฌ์ฉํด๋ณธ๋ค.
๐ useDebugValue
-
useDebugValue๋ React ๊ฐ๋ฐ์ ๋๊ตฌ์์ ์ฌ์ฉ์ Hook ๋ ์ด๋ธ์ ํ์ํ๋ ๋ฐ์ ์ฌ์ฉํ ์ ์๋ค.
function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); useDebugValue(isOnline ? 'Online' : 'Offline'); return isOnline; }
๐ ๋ค๋ฅธ Hooks
- ๐ ์ฐธ๊ณ ๋งํฌ : React-Hooks ๊ณต์ ๋ฌธ์
- ๋ค๋ฅธ ๊ฐ๋ฐ์๊ฐ ๋ง๋ Hooks๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ค์นํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
- ๐ ์ฐธ๊ณ ๋งํฌ : https://nikgraf.github.io/react-hooks
- ๐ ์ฐธ๊ณ ๋งํฌ : https://github.com/rehooks/awesome-react-hooks
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ