개발 이야기/frontend

Electron 이벤트값을 다르게 설정하여 리액트 컴포넌트 재사용하기

thisisamrd 2023. 10. 13.

Electron.js와 React.js를 이용해 채팅 팝업창을 만들면서, 이전에 만들어둔 TitleMenuBar라는 컴포넌트를 재사용하고 싶어졌다.

 


일렉트론은 원래 디폴트로 제공해주는 상단 메뉴바가 있는데, 내가 원하는 UI로 디자인하기 위해 아래처럼 상단 메뉴바를 없앴다.

그리고 TitleMenuBar를 리액트에서 새로 만들어 일렉트론에서 기본으로 제공해주는 이벤트인 minimize()라던지 close()등에 연결하였다.

 

BrowserWindow 코드

mainWindow = new BrowserWindow({
		//생략
		frame: false, // 여기서 default menu값을 없앰
	});
      
    // TitleMenuBar.js에서 발신한 ipcMain값을 읽은 뒤 이벤트 발생시킴
	ipcMain.on('minimize-main-window', () => {
		mainWindow.minimize();
	});

	ipcMain.on('close-main-window', () => {
		mainWindow.close();
	});

	ipcMain.on('extra-menu', (event) => {
		const menu = Menu.buildFromTemplate(menuTemplate);
		menu.popup(BrowserWindow.fromWebContents(event.sender));
	});

 

 

TitleMenuBar 관련 코드

 

참고로 TitleMenuBar.js에서는 이런식으로 일렉트론에 전달을 했다. 

메뉴바 우측 아이콘에 각각 onClick함수가 발생하면 electron.send에 명명된 이벤트를 전달한다.

 

function TitleMenuBar() {
	
	const handleMinimize = () => {
		electron.send('minimize-main-window');
	};

	const handleClose = () => {
		electron.send('close-main-window');
	};

	const handleMenu = () => {
		electron.send('extra-menu');
	};
    
    // 생략
    }

 

 

문제

그런데 오늘 풀어야 할 과제는 popup창 브라우저에 TitleMenuBar 컴포넌트를 재사용하되 main.js에 보낼 이벤트값을 다르게 설정해야 한다는 것이었다.

현재 코드는 chat popup window의 메뉴, 최소화, 닫힘 버튼 등을 클릭했을 때 chat popup window가 아니라 main window의 메뉴, 최소화, 닫힘 기능이 활성화되기 때문이다.

 

 

위 문제를 어떻게 해결할 수 있을까?

 

 

해결 방법

 

Electron 이벤트값을 다르게 설정하여 리액트 컴포넌트 재사용하기

 

 

TitleMenuBar.js를 아래처럼 수정하면 된다.

function TitleMenuBar({ 
    minimizeEvent = 'minimize-main-window', 
    closeEvent = 'close-main-window',
    menuEvent = 'extra-menu' 
}) {
    const handleMinimize = () => {
        electron.send(minimizeEvent);
    };

    const handleClose = () => {
        electron.send(closeEvent);
    };

    const handleMenu = () => {
        electron.send(menuEvent);
    };

    ...
}

 

참고로 위 코드는 매개변수가 제공되지 않을 경우 기본값을 사용할 수 있다는 속성이 들어간다.

이게 무슨말이냐면 바로 이런것이다. 

function greet(name = "Guest") {
    console.log("Hello, " + name);
}

greet();  // Hello, Guest
greet("John");  // Hello, John

 

위와 같이 구성하면, ChatPopup.js에서 TitleMenuBar 컴포넌트를 사용할 때 원하는 이벤트 명을 prop으로 전달할 수 있다.

function ChatPopup({ onClose }) {
    ...
    return (
        <>
            <TitleMenuBar 
                minimizeEvent="minimize-chat-popup"
                closeEvent="close-chat-popup"
            />
            ...
        </>
    );
}

 

마지막으로, main.js에서 해당 이벤트를 처리할 수 있는 ipcMain 리스너를 추가한다.

채팅 팝업창을 열 때 BrowserWindow 이름을 chatPopupWindow라고 선언해두었기 때문에, main window에서 사용하던 이벤트값을 해당 변수명에 연결시키면 된다.

 

ipcMain.on('open-chat-popup', (event, chatName) => {
	let chatPopupWindow = new BrowserWindow({
		//생략
		frame: false,
	});

	// 생략
    
	chatPopupWindow.on('closed', () => {
		chatPopupWindow = null;
	});

	ipcMain.on('minimize-chat-popup', () => {
		chatPopupWindow.minimize();
	});

	ipcMain.on('close-chat-popup', () => {
		chatPopupWindow.close();
	});

	ipcMain.on('menu-chat-popup', (event) => {
		const menu2 = Menu.buildFromTemplate(chatMenuTemplate);
		menu2.popup(BrowserWindow.fromWebContents(event.sender));
	});
});

댓글