-
React :: Hook, useState, useEffect, ์ฌ์ฉ์ ์ ์ HookPROGRAMMING/React 2021. 3. 31. 13:09
Hook
Hook์ ํจ์ ์ปดํฌ๋ํธ์์ React state์ ์๋ช ์ฃผ๊ธฐ ๊ธฐ๋ฅ(lifecycle features)์ “์ฐ๋(hook into)“ํ ์ ์๊ฒ ํด์ฃผ๋ ํจ์๋ฅผ ๋งํ๋ค.
useState, useEffect ์ ๊ฐ์ ๋ด์ฅ Hook ์ ์ฌ์ฉํ๊ฑฐ๋, ์ง์ ์ ์ํด์ ์ฌ์ฉํ ์๋ ์๋ค.
Hook ์ฌ์ฉ ๊ท์น
Hook์ ๊ทธ๋ฅ JavaScript ํจ์์ด์ง๋ง, ๋ ๊ฐ์ง ๊ท์น์ ์ค์ํด์ผ ํ๋ค.
- **์ต์์(at the top level)**์์๋ง Hook์ ํธ์ถ! ๋ฐ๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ์ค์ฒฉ๋ ํจ์ ๋ด์์ Hook์ ์คํํ๋ฉด ์๋จ
- React ํจ์ ์ปดํฌ๋ํธ ๋ด์์๋ง Hook์ ํธ์ถ! (๋น์ฐํ, Class ์์์๋ Hook ์ ๋์ํ์ง ์์) ์ผ๋ฐ JavaScript ํจ์์์๋ Hook์ ํธ์ถํ๋ฉด ์๋จ
๊ทธ๋ผ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋ํ์ ์ธ ๋ด์ฅ Hook ๋ ๊ฐ๋ฅผ ์ดํด๋ณด์.
useState
useState ๋ ํด๋์ค ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๋ state ์ ๊ฐ๋ ์ ํจ์ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๋๋ก ํ๋ ๊ฒ์ด๋ค.
๋จผ์ , ํจ์ ์ปดํฌ๋ํธ์ ํํ๋ฅผ ์ง๊ณ ๋์ด๊ฐ๋ณด์.
ํจ์ ์ปดํฌ๋ํธ๋ ํฌ๊ฒ ๋ค์์ ๋ ํํ๋ก ์กด์ฌํ๋ค.
function Example(props) { // ์ฌ๊ธฐ์ Hook์ ์ฌ์ฉํ ์ ์๋ค return <div />; }
const Example = (props) => { // ์ฌ๊ธฐ์ Hook์ ์ฌ์ฉํ ์ ์๋ค return <div />; }
๊ทธ๋ฆฌ๊ณ , ํด๋์ค ์ปดํฌ๋ํธ์์ state ๋ ๋ค์๊ณผ ๊ฐ์ ํํ๋ก ์ฌ์ฉ๋์๋ค.
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { ... } }
์ด์ ์ Props, State ๋ฅผ ๋ฐฐ์ธ ๋ State ๋ ํด๋์ค ์ปดํฌ๋ํธ์์๋ง ์ฌ์ฉํ ์ ์๋ค๊ณ ํ๋ค.
๊ทธ๋ผ ํจ์ ์ปดํฌ๋ํธ์์๋ State ์ ๊ฐ๋ ์ ์ฌ์ฉํ ์ ์๋๊ฐ์ ๋ํ ์๋ฌธ์ ๊ฐ์ก์๋๋ฐ,
useState ๋ฅผ ์ฌ์ฉํด์ State ์ ๊ฐ๋ ์ ์ฌ์ฉํ ์ ์๋ค.
useState ์ฌ์ฉ ํ๋ฆ (์์ฝ)
useState ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํฌ๊ฒ ๋ค์์ ์ธ ๋จ๊ณ๋ก ์ด๋ฃจ์ด์ง๋ค.
1) useState ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด, useState Hook ๋ฅผ React ์์ ๊ฐ์ ธ์จ๋ค.
import React, { useState } from 'react';
2) useState ๋ก state ๋ณ์๋ฅผ ๋ง๋ค์ด์ค๋ค.
const [count, setCount] = useState(0);
(์ฌ๊ธฐ์ ๋๊ดํธ๊ฐ ์๋ฏธํ๋ ๊ฒ์ "๋ฐฐ์ด ๊ตฌ์กฐ ๋ถํด"๋ผ๋ JavaScript ๋ฌธ๋ฒ์ด๋ค)
3) useState ๊ฐ ๋ง๋ค์ด์ค state ๋ฅผ ๊ฐฑ์ ํ ์ ์๋ ํจ์๋ก state ๋ณ์๋ฅผ ๊ฐฑ์ ํ๋ค.
React ๋ ๋ณํ๋ฅผ ์ธ์งํ๊ณ , ํด๋น ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋งํ๋ค.
import React, { useState } from 'react'; 2: function Example() { const [count, setCount] = useState(0); 5: return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>10: Click me </button> </div> ); }
useState Hook ์ ์ฌ์ฉํ๋ ํ๋ฆ์ ์ดํด๋ดค๋ค.
๊ทธ๋ฌ๋ฉด, useState ์ ์ธ์๋ก ๋๊ฒจ์ค ๊ฒ์ ๋ฌด์์ผ๋ก ๋ฐ์ ๊ฒ์ ๋ฌด์์ผ๊น?
๋จธ๋ฆฟ์์ useState ๋ฅผ ์ฌ์ฉํ๋ ํ๋ฆ์ ๊ทธ๋ ค๋๊ณ , ๋ ์ธ๋ถ์ ์ผ๋ก ์ดํด๋ณด์.
useState ์ธ๋ถ ์ฌํญ
useState Hook ์ ์ปดํฌ๋ํธ ๋ด์์ ํธ์ถํ์ฌ ์ฌ์ฉํ๋ฉด ๋๋ค.
(ํจ์ ์ปดํฌ๋ํธ๋ this ๋ฅผ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์ ์ง์ useState ๋ฅผ ํธ์ถํด์ ์ฌ์ฉ)
const [fruit, setFruit] = useState('apple');
์ด๊ฑด ๋ฌด์์ ์๋ฏธํ ๊น?
๋จผ์ useState ์ ์ธ์๋ก ๋๊ฒจ์ค 'apple' ์ fruit state ์ ์ด๊ธฐ๊ฐ์ด๋ค.
๊ทธ๋ฆฌ๊ณ useState ๋ 'apple' ์ ์ด๊ธฐ๊ฐ์ผ๋ก ๊ฐ์ง๋ fruit state ์ fruit ์ ๊ฐ์ ๊ฐฑ์ ํด์ค ์ ์๋ setFruit ํจ์๋ฅผ ๋ฐํํด์ฃผ๋ ๊ฒ์ด๋ค.
์ฆ, useState ๋ฅผ ํตํด ์ ๋ ๊ฐ์ ๋ฐ์์๋ค๋ฉด ์ด๋ ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
//state ๊ฐ ๋ณ๊ฒฝํ๊ธฐ setFruit('banana') //state ๊ฐ ๊ฐ์ ธ์ค๊ธฐ <p>You're fruit is {fruit} !</p>
์ด๋ฌ๋ฉด fruit state ๊ฐ์ 'apple' ์ด ์๋ 'banana' ๋ก ๋ณ๊ฒฝ๋๋ ๊ฒ์ด๋ค.
์ด๊ฒ ๋ง์ผ ํด๋์ค ์ปดํฌ๋ํธ์๋ค๋ฉด, this.state.fruit ๋ก ์ ๊ทผํด์ผ ํ๊ณ state ๊ฐ์ ๊ฐ์ ธ์ค๋ ๋ฐ์๋ {this.state.fruit} ๋ฅผ ์ฌ์ฉํด์ผ ํ์ ๊ฒ์ด๋ค.
//state ๊ฐ ๋ณ๊ฒฝํ๊ธฐ this.setState({fruit: 'banana'}) //state ๊ฐ ๊ฐ์ ธ์ค๊ธฐ <p>You're fruit is {this.state.fruit} !</p>
๋์ฑ ๊ฐํธํ๊ณ ์ง๊ด์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.
์ ๋ฆฌํ์๋ฉด, useState ์ ์ธ์๋ก ๋ง๋ค state ์ ์ด๊ธฐ๊ฐ์ ๋์ ธ์ฃผ๋ฉด, useState ๊ฐ state ์ state ๋ฅผ ๊ฐฑ์ ํ ํจ์๋ฅผ ๋ฐํํด์ฃผ๋ ๊ฒ!
๋ค์๊ณผ ๊ฐ์ด ์ฌ๋ฌ state ๋ณ์๋ฅผ ์ ์ํด๋๊ณ ์ฌ์ฉํ ์ ์๋ค.
const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
useEffect
React class์ componentDidMount ๋ componentDidUpdate, componentWillUnmount์ ๊ฐ์ ๋ชฉ์ ์ผ๋ก ์ ๊ณต๋์ง๋ง, ํ๋์ API๋ก ํตํฉ๋ ๊ฒ์ด๋ค.
(์ฐธ๊ณ : 2021.03.21 - [PROGRAMMING/React] - React :: ์๋ช ์ฃผ๊ธฐ (Lifecycle))
์ ์ด๋ค์ ํตํฉํ๊ณ , ๊ทธ๊ฒ ์ฅ์ ์ด ๋ ๊น?
๋ค์ ๋ด์ฉ์ ์๊ฐํด๋ณด์.
๋ ๋๋ง ์ดํ์ ํญ์ ๊ฐ์ ์ฝ๋๊ฐ ์คํ๋๊ธธ ๋ฐ๋๋ค๋ฉด, ์ด๋ค ์๋ช ์ฃผ๊ธฐ ํจ์๋ฅผ ์ฌ์ฉํด์ผ ํ ๊น?
์ปดํฌ๋ํธ๊ฐ ์ด์ ๋ง ๋ง์ดํธ ๋ ๊ฒ์ธ์ง, ์๋๋ฉด ์ ๋ฐ์ดํธ๋ ๊ฒ์ธ์ง์ ์๊ด์์ด ์ฝ๋๋ฅผ ์คํํด์ผ ํ๋ค.
๊ทธ๋ผ, ์๋ช ์ฃผ๊ธฐ ํจ์๋ฅผ ์๊ฐํ์ ๋ componentDidMount์ componentDidUpdate ์ ๋ชจ๋ ์ฌ์ฉํด์ผ ํ๋ค.
๊ทธ๊ฒ๋ ๊ฐ์ ์ฝ๋๋ก ์คํํด์ผํ๋ค. ๋ค์์ฒ๋ผ..
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; }
์ด๋ ์๋นํ ๋นํจ์จ์ ์ธ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
๋ฐ๋ฉด useEffect Hook ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋งค ๋ ๋๋ง ์ดํ์ effects๋ฅผ ์คํํ๋ค. ์ฒซ ๋ฒ์งธ ๋ ๋๋ง๋ ํฌํจํด์!
(์ฐ๋ฆฌ๊ฐ React ์๊ฒ ๋๊ธด ์ด Hook ํจ์๋ฅผ 'effect' ๋ผ๊ณ ๋ถ๋ฅธ๋ค.)
๊ทธ๋์ ๊ทธ๋ฅ ์ด๋ ๊ฒ ์์ฑํด์ฃผ๋ฉด ๋๋ค.
* useEffect Hook ์ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ React ๋ก๋ถํฐ ๋ฐ์์์ผ ํ๋ค.
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; });
์ค๋ณต๋ ์ฝ๋๋ ์๊ณ , ๊ฐ๋ ์ฑ๋ ๋์๋ค.
useEffect ํน์ง
- ์ปดํฌ๋ํธ ๋ด์์ ์ฌ์ฉํ๋ค.
-> effect ๋ฅผ ํตํด state ๋ณ์์ ๊ฐ์ข prop ์๋ ์ ๊ทผ ํ ์ ์๋๋ก! - ๋ ๋๋ง ์ดํ์ ๋งค๋ฒ ์ํ๋๋ค.
(๋ง์ดํธ, ์ ๋ฐ์ดํธ๋ผ๋ ๊ฐ๋ ๋ณด๋ค๋ ๋ ๋๋ง ์ดํ์ ๋ฐ์ ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.)
React ๋ effect ๊ฐ ์ํ๋๋ ์์ ์ ์ด๋ฏธ DOM ์ด ์ ๋ฐ์ดํธ ๋์์์ ๋ณด์ฅํ๋ค. - useState์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ปดํฌ๋ํธ ๋ด์์ ์ฌ๋ฌ ๊ฐ์ effect๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
Clean-Up
์ปดํฌ๋ํธ๋ฅผ ์ ๋ฆฌ(Clean-Up) ์ด effect ์ ํ์ํ ๋๊ฐ ์๋ค.
๊ทธ๋ด ๋ useEffect ์์ ์ ๋ฆฌํ๋ ๊ธฐ๋ฅ์ ๊ฐ์ง ํจ์๋ฅผ ๋ฐํํ๋ฉด ๋ฉ๋ค.
effect ๊ฐ ํจ์๋ฅผ ๋ฐํํ๋ฉด ๋ฆฌ์กํธ๋ ๊ทธ ํจ์๋ฅผ ์ ๋ฆฌ๊ฐ ํ์ํ ๋ ์คํ์ํจ๋ค.
์ด๋ (๊ธฐ๋ณธ์ ์ผ๋ก) ํ ๋ฒ์ด ์๋๋ผ, ๋ ๋๋ง์ด ์คํ๋ ๋๋ง๋ค, ๋งค๋ฒ ๋ฆฌ๋ ๋๋ง ์์ ์ ๋ฆฌํ๊ฒ ๋๋ค.
์ฝ๋๋ฅผ ๋ณด์.
import React, { useState, useEffect } from 'react'; function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); // effect ์ดํ์ ์ด๋ป๊ฒ ์ ๋ฆฌ(clean-up)ํ ๊ฒ์ธ์ง ํ์ํ๋ค. return function cleanup() { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
์ด ์ฝ๋๋ ์น๊ตฌ์ ์จ๋ผ์ธ ์ํ๋ฅผ ๊ตฌ๋ ํ ์ ์๋ ChatAPI ๋ชจ๋์ ์ฌ์ฉํ ์์ด๋ค.
์ปดํฌ๋ํธ๊ฐ ์ฒซ ๋ง์ดํธ ๋ ๋๋ฅผ ํฌํจํ์ฌ, ๋งค๋ฒ ๋ฆฌ๋ ๋๋ง ํ ๋๋ง๋ค ์น๊ตฌ ๊ตฌ๋ -๊ตฌ๋ ํด์ง๋ฅผ ๋ฐ๋ณตํ๋ค.
์ด๋ ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํ ์ ์์ง๋ง, ์ฑ๋ฅ ์ ํ(๋งค๋ฒ ์ ๋ฆฌํ๊ณ ๋ค์ ์คํ)๊ฐ ์ฐ๋ ค๋ ์ ์๋ค.
์ด ์ ๋ค์ ์ดํด๋ณด์.
๋ฒ๊ทธ ๋ฐฉ์ง
์ด์ ์ ์ฝ๋๋ก ์ด๋ป๊ฒ ๋ฒ๊ทธ ๋ฐฉ์ง๊ฐ ๋๋๊ณ ์๊ฐํ ์๋ ์์ง๋ง,
๋ง์ผ ํ๋ก๊ทธ๋จ์ด ๋์๊ฐ๋ ์ค์ (์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์ ํ์๋์ด์๋ ๋์) ์น๊ตฌ์ id, ์ฆ friend.id ๊ฐ ๋ฐ๋์์ผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
๋ค๋ฅธ ์น๊ตฌ์ ์จ๋ผ์ธ ์ํ๋ฅผ ๊ณ์ ํ์ํ๊ฒ ๋ ๊ฒ์ด๋ค. ์ด๋ ๋ช ๋ฐฑํ ๋ฒ๊ทธ์ด๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ํด๋์ค ์ปดํฌ๋ํธ์๋ค๋ฉด componentDidUpdate๋ฅผ ์ฌ์ฉํ๊ฒ ์ง๋ง,
useEffect ๋ ๋ฆฌ๋ ๋๋ง ํ ๋๋ง๋ค , ๋ค์์ effect ๋ฅผ ์ ์ฉํ๊ธฐ ์ ์ ์ด์ ์ effect ๋ ์ ๋ฆฌํ๋ค.
์ฆ ์์ ์ฝ๋์ ์คํ ๊ณผ์ ์ ๊ฐ์ํํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
// { friend: { id: 100 } } state์ ์ฌ์ฉํ์ฌ ๋ง์ดํธํ๋ค. ChatAPI.subscribeToFriendStatus(100, handleStatusChange); // ์ฒซ๋ฒ์งธ effect๊ฐ ์๋ํ๋ค. // { friend: { id: 200 } } state๋ก ์ ๋ฐ์ดํธํ๋ค.. ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // ์ด์ ์ effect๋ฅผ ์ ๋ฆฌ(clean-up)ํ๋ค. ChatAPI.subscribeToFriendStatus(200, handleStatusChange); // ๋ค์ effect๊ฐ ์๋ํ๋ค. // { friend: { id: 300 } } state๋ก ์ ๋ฐ์ดํธํ๋ค. ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // ์ด์ ์ effect๋ฅผ ์ ๋ฆฌ(clean-up)ํ๋ค. ChatAPI.subscribeToFriendStatus(300, handleStatusChange); // ๋ค์ effect๊ฐ ์๋ํ๋ค. // ๋ง์ดํธ๋ฅผ ํด์ ํ๋ค. ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // ๋ง์ง๋ง effect๋ฅผ ์ ๋ฆฌ(clean-up)ํ๋ค.
์ด๋ ๊ฒ ํ๋ฉด ํด๋์ค ์ปดํฌ๋ํธ์์ ์์ฃผ ๋ฐ์ํ๋, ์ ๋ฐ์ดํธ ๋ก์ง (componentDidUpdate) ์ ๋นผ๋จน์ผ๋ฉด์ ๋ฐ์ํ๋ ๋ฒ๊ทธ๋ฅผ ์๋ฐฉํ ์ ์๋ค!
์ฑ๋ฅ ์ ํ ๋ฐ์์ด ์ฐ๋ ค๋๋ค๋ฉด...
์น๊ตฌ id ๊ฐ ๋ณ๊ฒฝ๋์ง ์์์ผ๋ฉด ๊ตณ์ด ๊ตฌ๋ ํด์ง๋ฅผ ํ ํ์๊ฐ ์๋ค.
๊ทธ๋์ ์์ useEffect ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ๋ฉด ์ฑ๋ฅ ์ ํ๋ฅผ ๋ฐฉ์งํ ์ ์๋ค.
useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }, [props.friend.id]); // props.friend.id๊ฐ ๋ฐ๋ ๋๋ง ์ฌ๊ตฌ๋ ํ๋ค.
์ด๋ ๊ฒ ํน์ ๊ฐ๋ค์ด ๋ฆฌ๋ ๋๋ง ์์ ๋ณ๊ฒฝ๋์ง ์๋๋ค๋ฉด ๋ฆฌ์กํธ๋ก ํ์ฌ๊ธ effect ๋ฅผ ๊ฑด๋๋ฐ๋๋ก ํ ์ ์๋ค.
useEffect ์ ๋ ๋ฒ์งธ ์ธ์๋ก "์ ๊ฒฝ์ฐ๋" ๊ฒ์ ๋๊ฒจ์ฃผ๋ฉด ๋๋ค.
๋ฐ๋ผ์, ์์ ์ฝ๋์์ props.friend.id ๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋ค๋ฉด ๊ตฌ๋ -์ฌ๊ตฌ๋ ์ ๋ฐ์ํ์ง ์๋๋ค. (ํด๋น effect ์คํ x)
๊ทธ๋ฐ๋ฐ, ์ด ์ต์ ํ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ฉด ๋ฐฐ์ด์ด ์ปดํฌ๋ํธ ๋ฒ์ ๋ด์์ ๋ฐ๋๋ ๊ฐ + effect ์ ์ํด ์ฌ์ฉ๋๋ ๊ฐ์ ๋ชจ๋ ํฌํจํ๋ค๋ ๊ฒ์ ๊ธฐ์ตํด์ผ ํ๋ค.
๋ง์ผ effect ๋ฅผ ๋ง์ดํธ์ ๋ง์ดํธ ํด์ ์์ ๋ฑ ํ ๋ฒ๋ง ์คํํ๊ณ ์ถ๋ค๋ฉด, useEffect ์ ๋ ๋ฒ์งธ ์ธ์๋ก ๋น ๋ฐฐ์ด([]) ์ ๋๊ฒจ์ฃผ๋ฉด ๋๋ค.
(์ด๋ ๊ฒ ์ฌ์ฉํ๋ ๊ฒ์ ํด๋์ค ์ปดํฌ๋ํธ์ componentDidMount์ componentWillUnmount ๋ชจ๋ธ์ ๋ ๊ฐ๊น๋ค)
Multiple useEffect
์ฌ๋ฌ effect ๋ฅผ ์ค์ ํด์ ๊ฐ effect ๊ฐ ํ๋ ์ผ์ ๊ตฌ๋ถํ ์ ์๋ค.
ํด๋์ค ์ปดํฌ๋ํธ์์ ์๋ช ์ฃผ๊ธฐ API ๋ฅผ ์ฌ์ฉํ ๋์๋ '์๊ธฐ'์ ๋ง์ถฐ์ ๊ธฐ๋ฅ์ ๋ค ๋ฃ์ด์ผ ํ์ง๋ง, useEffect ๋ '๊ธฐ๋ฅ'์ ๋ง์ถฐ์ ๋ถ๋ฆฌํ ์ ์๋ค.
์ฆ, ๊ตฌ๋ ์ ์ถ๊ฐํ๊ณ ์ ๊ฑฐํ๋ ๋ก์ง๊ณผ ๊ฐ์ด ์๋ก ๊ด๋ จ ์๋ ์ฝ๋๋ค์ ํ๊ตฐ๋ฐ์ ๋ชจ์์ ์์ฑํ ์ ์๋ค.
function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); // ... }
์ฌ์ฉ์ ์ ์ Hook
์ฌ์ฉ์ ์ ์ Hook ์ ๋ง๋ค์ด๋๊ณ ์ฌ์ฉํ ์ ์๋ค.
- ์ด๋ฆ์ด use๋ก ์์ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํจ์์ด๋ค.
- ๋ค๋ฅธ Hook์ ํธ์ถํ ์ ์๋ค.
- ์กฐ๊ฑด๋ถ ํจ์๊ฐ ์๋์ด์ผ ํ๋ค.
- ๊ฐ์ Hook์ ์ฌ์ฉํ๋ ๋ ๊ฐ์ ์ปดํฌ๋ํธ๋ state๋ฅผ ๊ณต์ ํ์ง ์๋๋ค
์์์ ๊ณ์ ์ดํด๋ณธ ์์ ์์ ์น๊ตฌ์ ์ํ๋ฅผ ๊ตฌ๋ ํ๊ณ , ์จ๋ผ์ธ ์ฌ๋ถ๋ฅผ ๋ฐํํ๋ ์ฝ๋๋ ๋ค๋ฅธ ๊ณณ์์๋ ์ฐ์ผ ์ ์๋ค.
๊ทธ๋ผ ๊ทธ ๋ถ๋ถ์ ์ฌ์ฉ์ ์ ์ Hook ๋ก ๋ง๋ค์ด์ ์ฌ์ฉํ๋ฉด ์ด๋จ๊น?
import { useState, useEffect } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { function handleStatusChange(status) { setIsOnline(status.isOnline); } ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; }
์ด useFriendStatus Hook์ ๋ชฉํ๋ ์น๊ตฌ์ ์ํ๋ฅผ ๊ตฌ๋ ํ๋ ๊ฒ์ด๋ค.
์ด๋ฅผ ์ํค friendID๋ฅผ ์ธ์๋ก ๋ฐ๊ณ ์จ๋ผ์ธ ์ํ์ ์ฌ๋ถ๋ฅผ ๋ฐํํ๋ค.
์ด์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค์ด ์ด Hook ์ ๊ฐ์ง๊ณ ๋ ๋ฆฝ์ ์ผ๋ก ํด๋น ๊ธฐ๋ฅ์ ์ํํ ์ ์๋ค.
Hook์ state ๊ทธ ์์ฒด๊ฐ ์๋๋ผ, ์ํ ๊ด๋ จ ๋ก์ง์ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๊ฐ ์ปดํฌ๋ํธ์์์ Hook ํธ์ถ์ ์์ ํ ๋ ๋ฆฝ๋ state๋ฅผ ๊ฐ์ง๊ณ , ์ฌ์ง์ด๋ ํ ์ปดํฌ๋ํธ ์์์ ๊ฐ์ custom Hook์ ๋ ๋ฒ ์ธ ์๋ ์๋ค.
Custom Hook์ ๊ธฐ๋ฅ์ด๋ผ๊ธฐ๋ณด๋ค๋ ์ปจ๋ฒค์ (convention)์ ๊ฐ๊น์ต๋๋ค. ์ด๋ฆ์ด ”use“๋ก ์์ํ๊ณ , ์์์ ๋ค๋ฅธ Hook์ ํธ์ถํ๋ค๋ฉด ๊ทธ ํจ์๋ฅผ custom Hook์ด๋ผ๊ณ ๋ถ๋ฅผ ์ ์์ต๋๋ค. useSomething์ด๋ผ๋ ๋ค์ด๋ฐ ์ปจ๋ฒค์ ์ linter ํ๋ฌ๊ทธ์ธ์ด Hook์ ์ธ์ํ๊ณ ๋ฒ๊ทธ๋ฅผ ์ฐพ์ ์ ์๊ฒ ํด์ค๋๋ค. - React ๊ณต์ ๋ฌธ์
๊ทธ๋์ ์ ์ฌ์ฉ์ ์ ์ Hook ์ ์๋์ ๊ฐ์ด ์๋ก ๋ค๋ฅธ ๋ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ ์ ์๋ค.
function FriendStatus(props) { const isOnline = useFriendStatus(props.friend.id); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
function FriendListItem(props) { const isOnline = useFriendStatus(props.friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li> ); }
Reference
React ๊ณต์ ๋ฌธ์
ko.reactjs.org/docs/hooks-overview.html
ko.reactjs.org/docs/hooks-effect.html
ko.reactjs.org/docs/hooks-custom.html
.
'PROGRAMMING > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React :: ์๋ช ์ฃผ๊ธฐ (Lifecycle) (0) 2021.03.21 React :: Component, Props, State (0) 2021.03.20 React :: Element Rendering (์๋ฆฌ๋จผ๋ ๋ ๋๋ง) (0) 2021.03.20 React : JSX (0) 2021.03.20 React :: React ์์ํ๊ธฐ (0) 2021.03.20