Posts Separating events from effects
Post
Cancel

Separating events from effects

https://react-ko.dev/learn/separating-events-from-effects

이벤트핸들러는 같은 상호작용을 다시 수행할때만 다시 실행된다. Effect는 props 또는 state의 변경 시 동기화를 위해 실행된다. 때때로 일부 값에 대한 응답으로 다시 실행되는 Effect와 그렇지 않은 Effect의 혼합이 필요할 때가 있다. 이 페이지는 이를 어떻게 수행할 수 있는지에 대한 글이다

Choosing between event handlers and Effects

어떤 동작이 이벤트 핸들러에 있어야하는지 effect에 있어야하는지 헷갈릴때가 있다. 이때는 코드가 실행되어야하는 이유에 대해 생각해보자

이벤트 핸들러

  • 특정 상호작용에 대한 응답으로 실행됨.(유저가 클릭했을때, 입력했을때)
  • 상호작용 없이 동작이 이루어지면 안됨.

Effect

  • state, prop 등 값이 변경되었을때 실행함.
  • 상호작용이 없어도 값이 변경되면 재실행해야함.

Reactive values and reactive logic

직관적으로 봤을때 이벤트 핸들러는 수동으로 실행되고, Effect는 자동으로 실행된다는 인식을 가질 수 있다. 좀 더 정확한 표현은 이벤트 핸들러는 반응형 로직이 아니고, Effect는 반응형 로직이라는 것이다.

반응형 값 (Reactive values)

  • 컴포넌트 본문 내부에 선언된 props, state, 변수
  • 렌더링 데이터 흐름에 참여하며, 리렌더링으로 인해 변경될 수 있다.

이벤트 핸들러 (Non-reactive logic)

  • 반응형 값이 변경되었다고 다시 실행되지 않아야한다.

Effect (Reactive logic)

  • 의존하는 반응형 값이 변경되면 다시 실행되어야한다.

Extracting non-reactive logic out of Effects

반응형 로직과 비반응형으로 동작해야하는 로직이 함께 Effect에 있는 경우가 있다.

예제 : 사용자가 채팅에 연결할때 알림을 표시하는데, props에서 현재 테마를 읽어 올바른 색상으로 알림을 표시.

1
2
3
4
5
6
7
8
9
10
11
12
13
function ChatRoom({ roomId, theme }) {  
	useEffect(() => {  
		const connection = createConnection(serverUrl, roomId);  
		connection.on('connected', () => {  
			showNotification('Connected!', theme);  
		});  
		connection.connect();  
		
		return () => {  
			connection.disconnect()  
		};  
	}, [roomId, theme]); // ✅ All dependencies declared

위 예제에서 theme는 반응형 값이기에 의존성에 추가했다. 하지만 이러면 theme가 변경될때마다 재연결이 이루어진다.

이 문제를 해결하는 가장 쉬운 방법은 theme를 의존성배열에서 제거하는 것이지만, 리액트에서 실험중인 useEffectEvent를 사용할 수 있다.

Declaring an Effect Event

useEffectEvent라는 실험적인 API로 위 문제를 해결할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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]); // ✅ All dependencies declared

Effect Event는 반응형 이벤트가 아니기에 의존성에서 생략해도 된다.

이벤트 핸들러 vs Effect Event

  • 이벤트 핸들러 : 사용자 상호작용에 대한 응답으로 실행
  • Effect Event : Effect에서 사용자가 촉발하는 별도의 이벤트

Effect Event는 사용하는 반응형 값이 변경시 자동으로 새로운 값으로 반영한다. 하지만 Effect를 다시 실행시키지 않는다.

Limitations of Effect Events

  • Effect 내부에서만 호출할 수 있음
  • 다른 컴포넌트나 Hook에 전달하면 안됨.

Effect Event는 Effect 코드의 비반응형 조각이기에, Effect Event는 이를 사용하는 Effect 옆에 있어야한다.

This post is licensed under CC BY 4.0 by the author.

Reusing logic with custom hooks

Synchronizing with effects

Comments powered by Disqus.