thumbnail

React에서 EventBus 사용하기

생성일2022. 8. 22.
태그
작성자지한솔

안녕하세요!
오늘은 vue에서 자주 썼던 eventBus를 react에서 만들어서 사용해보려고 합니다.
 
사실은 eventbus를 사용하는 방식만 안다면 vue, react 구분없이 개발할 수 있지만, 요즘엔 html 기초보다 바로 react를 배우시는 분들이 많아서 eventbus를 사용하는데 어려움을 느끼시는 분들이 있는 것 같아 이렇게 올려봅니다!

우선 eventBus란?

eventBus란 다른 컴포넌트끼리 데이터를 주고받을 수 있는 방식입니다. 하지만 이 방식은 부모 - 자식 간의 관계가 필요 없이 전혀 다른 컴포넌트끼리 데이터 전송이 가능하다는 장점이 있습니다.
 
그럼 eventBus를 주로 어떨때 사용하나요? 라고 물어볼 수 있습니다. 저같은 경우에는 vue와 react를 모두 개발하는 사람으로써, 전역으로 모달, 로딩페이지를 뺄때 주로 사용합니다.
 
모든 컴포넌트마다 모달과 로딩을 위해서 export 한 컴포넌트를 import하는 불필요한 작업을 eventBus를 통해 없앨 수 있기 때문이죠!
 
그럼 react에서 어떻게 eventBus를 사용할 수 있을까요?
 
사용방법은 간단합니다. eventBus를 수신할 on, 전송의 emit을 addEventListener와 dispatchEvent를 통해 이벤트를 만들어주면 됩니다.
 
export const eventBus = { on(event, callback) { document.addEventListener(event, callback); }, emit(event, data) { // create a custom event const myEvent = new CustomEvent(event, { detail: data }); // dispatch the event document.dispatchEvent(myEvent); }, remove(event, callback) { document.removeEventListener(event, callback); }, };
 
이렇게 한다면 수신할 컴포넌트에서 on을 통해 원하는 이벤트를 생성, 전송할 컴포넌트에서 emit을 통헤 dispatchEvent를 사용해 데이터를 전송해주는 것입니다.
 
import React, { useEffect, useState } from "react"; import { eventBus } from "./eventBus"; export const Event = () => { const [isVisible, setIsVisible] = useState(false) const [isTitle, setIsTitle] = useState('') const [isMessage, setIsMessage] = useState('') useEffect(() => { eventBus.on('loading', setting) return () => eventBus.remove('loading') }) const setting = ({ detail: { title, message, visible } }) => { if (visible) { setIsTitle(title) setIsMessage(message) setIsVisible(visible) } } if (isVisible) { return ( <div style={{ width: '100vw', height: '100vh', position: 'relative', display: 'flex', justifyContent: 'center', alignItems: 'center' }}> <div style={{ backgroundColor: 'black', opacity: '0.3', width: '100%', position: 'absolute', height: '100%', zIndex: 100 }}></div> <div style={{ width: '300px', height: '200px', display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: 101, backgroundColor: '#fff' }}> <div><span>{isTitle}<br />{isMessage}</span></div> <button onClick={() => setIsVisible(false)}>확인</button> </div> </div> ) } }
 
이렇게 수신할 컴포넌트에서는 event 명과, 실행할 함수를 지정해두면 됩니다. 해당 예제에서는 loading이라는 이벤트 명을 생성해두었으며 loading이 수신될때마다 setting 함수를 실행시켜 전송자가 보낸 타이틀, 메세지를 화면에 뿌려주게 죕니다.
 
import React from "react"; import { eventBus } from "./eventBus"; export const Main = () => { const onClick = () => { eventBus.emit('loading', { title: 'loading', message: '로딩중입니다.', visible: true }) } return ( <div> <button onClick={onClick}>Loading</button> </div> ) }
 
전송하는 컴포넌트에서는 loading이라는 명칭을 수신하는 컴포넌트로 title, message, visible을 전송해줘! 라는 구문입니다.
 
이렇게 한다면 최상단 컴포넌트에서 수신, 전송 컴포넌트를 같은 뎁스에 선언하고 eventBus를 통해 원하는 곳 어디서든 불러올 수 있을 겁니다.
 
저는 주로 자주 사용되는 모달, 로딩시에 사용하고 있습니다 이렇게 하면 불필요한 선언은 줄어들 것이고, 혹시나 파일명이 수정되더라도 선언된 곳들 전부를 돌며 변경할 필요도 없어지게 될 것입니다.
 
하지만 eventBus를 남발한다면 관리에 있어서 어려움이 존재할 수 있습니다..
 
오늘은 이렇게 알아두면 편리한 eventBus에 대해 포스팅을 써봤습니다. 저도 vue에서만 사용해봤지 실제로 react에서는 이번에 프로젝트를 통해 사용해봤습니다.
 
너무 편리한 나머지 공유하고 싶어서... ㅎㅎ 궁금한 점은 댓글을 통해서 질문해주시면 답변해놓겠습니당 감사합니다 :D