You will learn
- effect ์์กด์ฑ ๋ฌดํ ๋ฃจํ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ
- ์์กด์ฑ์ ์ ๊ฑฐํ๋ ๋ฐฉ๋ฒ
- effect์ ๋ฐ์ํ์ง ์๊ณ effect์ ๊ฐ์ ์ฝ๋ ๋ฐฉ๋ฒ
- ๊ฐ์ฒด์ ํจ์์ ๋ํ ์์กด์ฑ์ ํผํด์ผ ํ๋ ์ด์ ์ ๋ฐฉ๋ฒ
- ๋ฆฐํฐ์ ์์กด์ฑ ๊ฒ์ฌ๋ฅผ ๋ฌด์ํ๋ฉด ์๋๋ ์ด์ ์ ๋์ ํด์ผ ํ ์ผ๋ค
์์กด์ฑ์ ์ ํํ ์ ์๋ค.
์ดํํธ๋ ์์กด์ฑ ๋ฐฐ์ด์ ์๋ ๊ฐ์ด ๋ณํ ๋ ๋ง๋ค ์คํ๋๊ธฐ ๋๋ฌธ์, ๋ถํ์ํ ์์กด์ฑ์ ๊ฐ์ง๋ค๋ฉด ์ดํํธ๊ฐ ๋๋ฌด ์์ฃผ ์คํ๋๊ฑฐ๋ ๋ฌดํ ๋ฃจํ์ ๋น ์ง ์ ์๋ค. ๊ทธ๋์ ๋ฌด์์ด ์ง์ง ์์กด์ฑ์ธ์ง, ๋ฌด์์ด ๋ถํ์ํ ์์กด์ฑ์ธ์ง ๊ตฌ๋ถํด์ผ ํ๋ค.
๊ฐ๋ฐ์๊ฐ ์ดํํธ๊ฐ ์ด๋ค ์์กด์ฑ์ ๊ฐ์ง๋์ง ์ ํํ ์ ์๋ค. ์ดํํธ ์์์ ์ฌ์ฉ๋๋ ๋ชจ๋ ๋ฐ์ํ ๊ฐ reactive value(state, props, ์ปดํฌ๋ํธ์์ ์ ์ธ๋ ๋ณ์)์ ๋ฐ๋์ ์์กด์ฑ ๋ฐฐ์ด์ ๋ค์ด๊ฐ์ผ ํ๋ค. ๊ทธ๋์ ์ด๋ค ์์กด์ฑ์ ์ ๊ฑฐํ๊ณ ์ถ๋ค๋ฉด ํด๋น ๊ฐ์ ๋น๋ฐ์ํ ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๊ฑฐ๋, ํด๋น ๊ฐ์ ์ฌ์ฉํ์ง ์๊ฑฐ๋ ํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค.
์์กด์ฑ ์ ๊ฑฐํ๊ธฐ
์ดํํธ๊ฐ ๋๋ฌด ์์ฃผ ์คํ๋๊ฑฐ๋, ์ผ๋ถ ์์กด์ฑ ๊ฐ์ '๋ฐ์'ํ์ง ์์ผ๋ฉด์ ์ต์ ๊ฐ์ ์ฌ์ฉํ๊ณ ์ถ๊ฑฐ๋ ํ ๋ ๋ค์๊ณผ ๊ฐ์ ์ฒดํฌ๋ฆฌ์คํธ๋ฅผ ํ์ธํด๋ณด๋๊ฒ์ด ๋์์ด ๋๋ค.
1. ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ก ์ฎ๊ฒจ์ผ ํ์ง ์์๊น?
๋ง์ฝ ์ดํํธ์ ์ด๋ค ์ฝ๋๊ฐ ํน์ ์ ์ ์ด๋ฒคํธ์ ์ข ์์ ์ด๋ผ๋ฉด? " You Might not need an Effect" ํ์ด์ง์์ ๋ดค๋ ๊ฒ ์ฒ๋ผ ์ด ๊ฒฝ์ฐ๋ ์ดํํธ๊ฐ ํ์ํ์ง ์๊ณ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ํฌํจ๋์ด์ผ ํ๋ค.
2. ์ดํํธ๊ฐ ์ฌ๋ฌ๊ฐ์ง ์ผ์ ํ๋๊ฒ ์๋๊น?
ํ๋์ ์ดํํธ์์ ์ฌ๋ฌ๊ฐ์ง ์ผ์ ํ๋ ๊ฒฝ์ฐ ์์กด์ฑ์ด ๋์ด๋๊ณ ๋ฐ๋ผ์ ์๋ก ๊ด๋ จ ์๋ ์ฝ๋๋ผ๋ฆฌ ์๋ก์ ์์กด์ฑ์ ์ํด ๋ถํ์ํ๊ฒ ์คํ๋ ์ ์๋ค.
3. ๋ค์ state๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด state๋ฅผ ์ฝ๋๊ฐ?
function ChatRoom({ roomId }) {
const [messages, setMessages] = useState([]);
useEffect(() => {
const connection = createConnection();
connection.connect();
connection.on('message', (receivedMessage) => {
setMessages([...messages, receivedMessage]);
});
return () => connection.disconnect();
}, [roomId, messages]); // โ
All dependencies declared
// ...
์ด๋ ๊ฒ ์์ฑํ๋ฉด ๋ฉ์์ง๊ฐ ๋์ฐฉํ ๋ ๋ง๋ค ์ดํํธ๊ฐ ์ฌ์คํ ๋๋ค. message ์ํ๋ฅผ ์ง์ ์ฌ์ฉํ๊ณ ์์กด์ค์ด๊ธฐ ๋๋ฌธ์ด๋ค.
function ChatRoom({ roomId }) {
const [messages, setMessages] = useState([]);
useEffect(() => {
const connection = createConnection();
connection.connect();
connection.on('message', (receivedMessage) => {
setMessages(msgs => [...msgs, receivedMessage]);
});
return () => connection.disconnect();
}, [roomId]); // โ
All dependencies declared
// ...
์ด๋ ๊ฒ ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ์ง ์๊ณ ์ ๋ฐ์ดํฐ ํจ์๋ฅผ ํตํด ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ฉด ๋๋ค.
4. ๊ฐ์ ๋ณํ์ '๋ฐ์'ํ์ง ์์ผ๋ฉด์ ๊ฐ์ ์ฝ๊ณ ์ถ์๊ฐ?
useEffectEventํ
๋ด์ฉ ์ฐธ๊ณ .
prop์ผ๋ก ๋ฐ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ดํํธ ์์์ ์ฌ์ฉํ๊ณ ์ถ์๋์๋ ์ ์ฉ๋๋ค.
function ChatRoom({ roomId, onReceiveMessage }) {
const [messages, setMessages] = useState([]);
useEffect(() => {
const connection = createConnection();
connection.connect();
connection.on('message', (receivedMessage) => {
onReceiveMessage(receivedMessage);
});
return () => connection.disconnect();
}, [roomId, onReceiveMessage]); // โ
All dependencies declared
// ...
onReceiveMessage ๋ ํจ์์ด๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๋ ๋๋ง๋ง๋ค ์ฃผ์๊ฐ์ด ๋ฌ๋ผ ์ดํํธ๋ ๋งค๋ฒ ๋ณ๊ฒฝ๋์๋ค๊ณ ํ๋จํ๊ณ ์ดํํธ๋ฅผ ์คํํ๋ค.
(๊ตณ์ด prop์ผ๋ก ๋ฐ์ ํจ์๊ฐ ์๋๋ผ ์ปดํฌ๋ํธ ์์์ ์ ์๋ ํจ์๋ ๋ง์ฐฌ๊ฐ์ง๋ค. ํ์ง๋ง ์ด๋ฌํ ๊ฒฝ์ฐ์๋ ํจ์๋ฅผ ์ดํํธ ์์ ์ ์ํ๋ฉด ํด๊ฒฐ ๊ฐ๋ฅํ๋ค. )
const onMessage = useEffectEvent(receivedMessage => {
onReceiveMessage(receivedMessage);
});
useEffect(() => {
const connection = createConnection();
connection.connect();
connection.on('message', (receivedMessage) => {
onMessage(receivedMessage);
});
return () => connection.disconnect();
}, [roomId]); // โ
All dependencies declared
5. ์ด๋ค ๋ฐ์ํ ๊ฐ์ด ์๋์น ์๊ฒ ๋ณ๊ฒฝ๋๋๊ฐ?
const options = {
serverUrl: serverUrl,
roomId: roomId
};
useEffect(() => {
const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [options]); // โ
All dependencies declared
์ ์ฝ๋์ ์๋๋ serverUrl์ด๋ roomId๊ฐ ๋ณ๊ฒฝ๋์ด option๊ฐ์ฒด๊ฐ ์
๋ฐ์ดํธ ๋๋ฉด ์ดํํธ๋ฅผ ์คํํ๋ ๊ฒ์ด์ง๋ง, ํจ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ์ฒด๋ ๋ชจ๋ ๋๋๋ง๋ง๋ค ๋ค๋ฅธ ์ฃผ์๊ฐ์ ๊ฐ์ง๋ฉด์ ๋ชจ๋ ๋ฆฌ๋ ๋๋ง๋ง๋ค ์ฑํ
๋ฐฉ ์ฐ๊ฒฐ์ด ๋ฐ๋ณต๋๋ค.
๋ฌธ์์์๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ์ํ๋ค. ๋ง์ฝ ์์กดํ๊ณ ์๋ ๊ฐ์ฒด๊ฐ ์ ์ ์ด๋ผ๋ฉด, ๋ณํ์ง ์๋๋ค๋ฉด, ๊ทธ๊ฒ์ ์ปดํฌ๋ํธ ๋ฐ์์ ์ ์ํ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ ์ด ์์์ฒ๋ผ roomId๊ฐ ๋ณ๊ฒฝ๋๋ค๋ฉด ์ด ๊ฐ์ฒด๋ ์ ์ ์ธ ๊ฐ์ฒด๊ฐ ์๋๋ผ ๋์ ์ธ ๊ฐ์ฒด๊ฐ ๋๋ค. ์ด๋ด๋ ์ด๋ป๊ฒ ํด์ผํ ๊น? ์ด๋ ๊ฒ option ๊ฐ์ฒด๋ฅผ ์ดํํธ ์์์ ์ ์ํ๋ฉด ๋๋ค.
useEffect(() => {
const options = {
serverUrl: serverUrl,
roomId: roomId
};
const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [roomId]); // โ
All dependencies declared
๊ทธ๋ฐ๋ฐ ๊ฐ์ฒด๊ฐ prop์ธ ๊ฒฝ์ฐ๋ ์ด๋ป๊ฒ ํด์ผํ ๊น? option ๊ฐ์ฒด๋ฅผ ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ก๋ถํฐ ์ ๋ฌ๋ฐ๋๋ค๋ฉด?
function ChatRoom({ options }) {
const [message, setMessage] = useState('');
const { roomId, serverUrl } = options;
useEffect(() => {
const connection = createConnection({
roomId: roomId,
serverUrl: serverUrl
});
connection.connect();
return () => connection.disconnect();
}, [roomId, serverUrl]); // โ
All dependencies declared
roomId์ serverUrl์ ์ถ์ถํด์ ์ฌ์ฉํ๋ฉด ๋๋ค.
์์ ๋ฌธ์
1. ์ธํฐ๋ฒ ์ด๊ธฐํ ๋ฌธ์
useEffect(() => {
console.log('โ
Creating an interval');
const id = setInterval(() => {
console.log('โฐ Interval tick');
setCount(count + 1);
}, 1000);
return () => {
console.log('โ Clearing an interval');
clearInterval(id);
};
}, [count]);
setCount์์ ์ง์ ๊ฐ์ ์ค์ ํ์ง ์๊ณ ์
๋ฐ์ดํฐ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
2. ์ ๋๋ฉ์ด์ ์ฌ์ด๋ฐ ๋ฌธ์
function Welcome({ duration }) {
const ref = useRef(null);
useEffect(() => {
const animation = new FadeInAnimation(ref.current);
animation.start(duration);
return () => {
animation.stop();
};
}, [duration]);
์ต์ ๊ฐ์ ์ฝ์ ์ ์์ง๋ง ์ดํํธ๊ฐ ๋ฐ์ํ์ง ์๊ฒ ๋ง๋ค์ด์ฃผ๋ useEffectEventํ
์ ์ฌ์ฉํ๋ฉด ๋๋ค.
const onAppear = useEffectEvent(animation => {
animation.start(duration);
});
useEffect(() => {
const animation = new FadeInAnimation(ref.current);
onAppear(animation);
return () => {
animation.stop();
};
}, []);
3. ์ฌ์ฐ๊ฒฐ ๋๋ ์ฑํ
export default function ChatRoom({ options }) {
useEffect(() => {
const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [options]);
prop์ผ๋ก ๋ฐ์ option์์ ํ์ํ ๊ฐ์ ์ถ์ถํด์ ์ฌ์ฉํด์ผ ํ๋ค.
export default function ChatRoom({ options }) {
const { roomId, serverUrl } = options;
useEffect(() => {
const connection = createConnection({
roomId: roomId,
serverUrl: serverUrl
});
connection.connect();
return () => connection.disconnect();
}, [roomId, serverUrl]);
4. ์ฌ์ฐ๊ฒฐ ๋๋ ์ฑํ 2
export default function ChatRoom({ roomId, createConnection, onMessage }) {
useEffect(() => {
const connection = createConnection();
connection.on('message', (msg) => onMessage(msg));
connection.connect();
return () => connection.disconnect();
}, [createConnection, onMessage]);
์ฌ๊ธฐ์ roomId์ isEncrypted๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์๋ก ์ฐ๊ฒฐํ๊ณ ์ถ๋ค๋ฉด? ์ผ๋จ createConnection๊ณผ onMessage๋ฅผ ์์กด์ฑ์์ ์ ๊ฑฐํด์ผ ํ๋ค.
onMessage์ ๊ฒฝ์ฐ ์ดํํธ ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
export default function ChatRoom({ roomId, createConnection, onMessage }) {
const onReceiveMessage = useEffectEvent(onMessage);
useEffect(() => {
const connection = createConnection();
connection.on('message', (msg) => onReceiveMessage(msg));
// ...
๊ทธ๋ฐ๋ฐ createConnection์ ๊ฒฝ์ฐ๋ ๋ณต์กํ๋ค. roomId์ isEncrypted์ ๋ฐ์ํด์ผ ํ๋ค.
์ฆ ์์ ๋ state๋ฅผ ๋ถ๋ชจ๋ก๋ถํฐ ๋ฐ์์์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
<ChatRoom
roomId={roomId}
isEncrypted={isEncrypted}
onMessage={msg => {
showNotification('New message: ' + msg, isDark ? 'dark' : 'light');
}}
/>
๊ทธ๋ฆฌ๊ณ createConnection์ด๋ผ๋ ํจ์๋ ๋ถ๋ชจ์์ ์ ์ํ์ง ์๊ณ Chatroom ์ปดํฌ๋ํธ์์ ์ ์ํ๋ค. ํ์ง๋ง ์ปดํฌ๋ํธ ์์์ ์ ์ํ ํจ์๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ ๋๋ง๋ง๋ค ์ฃผ์๊ฐ์ด ๋ฐ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ๋จ์ํ ์ปดํฌ๋ํธ ์์์ ์ ์ํด์๋ ์๋๊ณ ์ดํํธ ์์ ์ ์ํด์ผ ํ๋ค.
useEffect(() => {
function createConnection() {
const options = {
serverUrl: 'https://localhost:1234',
roomId: roomId // Reading a reactive value
};
if (isEncrypted) { // Reading a reactive value
return createEncryptedConnection(options);
} else {
return createUnencryptedConnection(options);
}
}
const connection = createConnection();
connection.on('message', (msg) => onReceiveMessage(msg));
connection.connect();
return () => connection.disconnect();
}, [roomId, isEncrypted]); // โ
All dependencies declared

