useEffectEvent๋Š” Effect ๋‚ด๋ถ€์˜ ๋น„๋ฐ˜์‘ํ˜• ๋กœ์ง์„ ์ถ”์ถœํ•ด Effect ์ด๋ฒคํŠธ๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” React Hook์ž…๋‹ˆ๋‹ค.

const onSomething = useEffectEvent(callback)

๋ ˆํผ๋Ÿฐ์Šค

useEffectEvent(callback)

Effect ์ด๋ฒคํŠธ๋ฅผ ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ์˜ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ useEffectEvent๋ฅผ ํ˜ธ์ถœํ•˜์„ธ์š”. Effect ์ด๋ฒคํŠธ๋Š” useEffect์™€ ๊ฐ™์ด Effect ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

import { useEffectEvent, useEffect } from 'react';

function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme);
});

useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.on('connected', () => {
onConnected();
});
connection.connect();
return () => connection.disconnect();
}, [roomId]);

// ...
}

์•„๋ž˜์—์„œ ๋” ๋งŽ์€ ์˜ˆ์‹œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

๋งค๊ฐœ๋ณ€์ˆ˜

  • callback: Effect ์ด๋ฒคํŠธ๋ฅผ ์œ„ํ•œ ๋กœ์ง์„ ํฌํ•จํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. useEffectEvent๋กœ Effect ์ด๋ฒคํŠธ๋ฅผ ์ •์˜ํ–ˆ์„ ๋•Œ, callback์€ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ํ•ญ์ƒ ์ตœ์‹ ์˜ props์™€ state ๊ฐ’์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์˜ค๋ž˜๋œ ํด๋กœ์ € ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜๊ฐ’

Effect ์ด๋ฒคํŠธ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. useEffect, useLayoutEffect ๋˜๋Š” useInsertionEffect ๋‚ด๋ถ€์—์„œ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜ ์‚ฌํ•ญ

  • Effect ๋‚ด๋ถ€์—์„œ๋งŒ ํ˜ธ์ถœํ•˜์„ธ์š”: Effect ์ด๋ฒคํŠธ๋Š” ์˜ค๋กœ์ง€ Effect ๋‚ด๋ถ€์—์„œ๋งŒ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” Effect ์ด์ „์— ๊ทธ๊ฒƒ์„ ์ •์˜ํ•˜์„ธ์š”. ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋‚˜ ํ›…์œผ๋กœ ๊ทธ๊ฒƒ์„ ์ „๋‹ฌํ•˜์ง€ ๋งˆ์„ธ์š”. eslint-plugin-react-hooks ๋ฆฐํ„ฐ(๋ฒ„์ „ 6.1.1 ๋˜๋Š” ์ตœ์‹ )๋Š” Effect ์ด๋ฒคํŠธ๋ฅผ ์ž˜๋ชป๋œ ๋งฅ๋ฝ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ œํ•œ์„ ๊ฐ•์ œํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ์˜์กด์„ฑ ์ง€๋ฆ„๊ธธ์ด ์•„๋‹™๋‹ˆ๋‹ค: Effect์˜ ์˜์กด์„ฑ ๋ฐฐ์—ด์— ์˜์กด์„ฑ์„ ์ ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด useEffectEvent๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. ์ด๊ฒƒ์€ ๋ฒ„๊ทธ๋ฅผ ์ˆจ๊ธฐ๊ณ  ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์„ ์–ด๋ ต๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ ์˜์กด์„ฑ์„ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ด์ „ ๊ฐ’์„ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด ref๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • ๋น„๋ฐ˜์‘ํ˜• ๋กœ์ง์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜์„ธ์š”: ๋ณ€ํ•˜๋Š” ๊ฐ’์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ๋กœ์ง์„ ์ถ”์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ๋งŒ useEffectEvent๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

์‚ฌ์šฉ๋ฒ•

์ตœ์‹  props์™€ state๋ฅผ ์ฝ๊ธฐ

์ „ํ˜•์ ์œผ๋กœ, Effect ๋‚ด๋ถ€์—์„œ ๋ฐ˜์‘ํ˜• ๊ฐ’์„ ์ฝ์„ ๋•Œ, ์˜์กด์„ฑ ๋ฐฐ์—ด์— ๊ทธ๊ฒƒ์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ ๋งˆ๋‹ค Effect๊ฐ€ ๋‹ค์‹œ ๋™์ž‘ํ•˜๋„๋ก ํ•˜๊ณ , ์ด๊ฒƒ์€ ๋ณดํ†ต ๋ฐ”๋žŒ์งํ•œ ๋™์ž‘์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋ช‡๋ช‡์˜ ์‚ฌ๋ก€์—์„œ, ์ด ๊ฐ’๋“ค์ด ๋ณ€ํ•  ๋•Œ Effect๊ฐ€ ๋‹ค์‹œ ๋™์ž‘ํ•˜์ง€ ์•Š๊ณ  Effect ๋‚ด๋ถ€์—์„œ ๊ฐ€์žฅ ์ตœ์‹ ์˜ props ๋˜๋Š” state๋ฅผ ์ฝ๊ณ  ์‹ถ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Effect ๋‚ด๋ถ€์—์„œ ์ด ๊ฐ’๋“ค์„ ๋ฐ˜์‘ํ˜•์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ ์—†์ด ์ตœ์‹  props์™€ state๋ฅผ ์ฝ๊ธฐ ์œ„ํ•ด Effect ์ด๋ฒคํŠธ ๋‚ด๋ถ€์— ๊ทธ๊ฒƒ๋“ค์„ ํฌํ•จํ•˜์„ธ์š”.

import { useEffect, useContext, useEffectEvent } from 'react';

function Page({ url }) {
const { items } = useContext(ShoppingCartContext);
const numberOfItems = items.length;

const onNavigate = useEffectEvent((visitedUrl) => {
logVisit(visitedUrl, numberOfItems);
});

useEffect(() => {
onNavigate(url);
}, [url]);

// ...
}

์ด ์˜ˆ์‹œ์—์„œ, url์ด ๋ฐ”๋€” ๋•Œ(์ƒˆ๋กœ์šด ํŽ˜์ด์ง€ ๋ฐฉ๋ฌธ์„ ๋กœ๊น…ํ•˜๊ธฐ ์œ„ํ•ด) Effect๋Š” ๋žœ๋” ์ดํ›„์— ๋‹ค์‹œ ๋™์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ numberOfItems๊ฐ€ ๋ฐ”๋€” ๋•Œ ๋‹ค์‹œ ๋™์ž‘ํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋กœ๊น… ๋กœ์ง์„ Effect ์ด๋ฒคํŠธ๋กœ ๊ฐ์‹ธ numberOfItems๋Š” ๋น„๋ฐ˜์‘ํ˜•์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ•ญ์ƒ Effect๋ฅผ ํŠธ๋ฆฌ๊ฑฐ ํ•˜๋Š” ๊ฒƒ ์—†์ด ์ตœ์‹ ์˜ ๊ฐ’์„ ์ฝ์Šต๋‹ˆ๋‹ค.

url๊ณผ ๊ฐ™์€ ๋ฐ˜์‘ํ˜• ๊ฐ’์„ Effect ์ด๋ฒคํŠธ์˜ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ, ์ด๋ฒคํŠธ ๋‚ด๋ถ€์˜ ๋น„๋ฐ˜์‘ํ˜• ๊ฐ’์— ์ ‘๊ทผํ•  ๋•Œ ์ด๊ฒƒ๋“ค์„ ๋ฐ˜์‘ํ˜•์œผ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.