Electron + React

Electron + React

참여할 수 없는 스레드입니다.

React + Electron : Component에서 ipcRenderer.on

@baealex
2020-02-18 13:51(Last Update: 2020-02-18 15:31)
class App extends Component {
    componentDidMount = () => {
        ipcRenderer.send('call-init');

        ipcRenderer.on('data-init', (event, arg) => {
            this.setState({
                information: arg,
            });
            this.id = arg.length;
        });
    }
}

componentDidMount에 작성해 놓으면 되고 Electron에선 기존과 똑같다!

ipcMain.on('data-save', (event, arg) => {
  fs.writeFile('save.data', JSON.stringify(arg), 'utf8', function(error) {
    console.log('error');
  });
})

ipcMain.on('call-init', (event, arg) => {
  fs.readFile('save.data', function(error, data) {
    event.sender.send('data-init', JSON.parse(data));
  })
})

이건 걍 내가 추가하는 부분이지만 JSON과 TEXT를 전환하려면 위와같이 JSON의 함수를 호출해서 사용해야 한다.

  • JSON => TEXT : JSON.stringify(var)
  • TEXT => JSON : JSON.parse(var)

React : 데이터 추가하기

@baealex
2020-02-18 10:12(Last Update: 2020-02-18 13:53)
class App extends Component {
    id = 2
    state = {
        information: [
            {
                id: 0,
                name: '배진오',
                phone: '010-0000-0000'
            },
            {
                id: 1,
                name: '홍길동',
                phone: '010-0000-0000'
            },
        ]
    }
    handleCreate = (data) => {
        const { information } = this.state;
        this.setState({
            information: information.concat({
                id: this.id++,
                ...data,
            })
        })
        //console.log(data)
    }
    render() {
        const { information } = this.state;
        return (
            <div>
                <PhoneForm 
                    onCreate={this.handleCreate}
                />
                {JSON.stringify(information)}
            </div>
        )
    }
}

React : 상위 컴포넌트에서 하위 컴포넌트의 값을 전달 받으려면?

@baealex
2020-02-18 10:12
class App extends Component {
    handleCreate = (data) => {
        console.log(data)
    }
    render() {
        return (
            <div>
                <PhoneForm 
                    onCreate={this.handleCreate}
                />
            </div>
        )
    }
}

위처럼 메서드 하나를 하위 컴포넌트의 props로 넘겨주고 하위 컴포넌트에서 해당 함수로 다음과 같이 값을 전달하면 된다.

class PhoneForm extends Component {
    state = {
        name: '',
        phone: '',
    }
    handleChange = (e) => {
        this.setState({
            [e.target.name]: e.target.value
        });
    }
    handleSubmit = (e) => {
        e.preventDefault();
        this.props.onCreate(this.state);
        this.setState({
            name: '',
            phone: '',
        })
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input
                    placeholder="이름"
                    value={this.state.name}
                    onChange={this.handleChange}
                    name="name"
                />
                <input
                    placeholder="전화번호"
                    value={this.state.phone}
                    onChange={this.handleChange}
                    name="phone"
                />
                {/*<div>{this.state.name} {this.state.phone}</div>*/}
                <button type="submit">등록</button>
            </form>
        )
    }
}

React + Electron : ipcRenderer import

@baealex
2020-02-17 15:47(Last Update: 2020-02-18 10:13)
const { ipcRenderer } = window.require("electron");

class App extends Component {
    ...
    btnClick = () => {
        ipcRenderer.send('button-click');
    }
    render() {
        ...
        return (
            <button onClick={this.btnClick}></button>
        )
        ...
    }
}

Electron에서는 아래에서 작성한 스토리와 마찬가지로 이벤트를 처리해주면 된다!

React + Electron : Example

@baealex
2020-02-12 15:55(Last Update: 2020-02-18 10:13)

이러한 환경을 구성한 대부분의 프로젝트가 yarn을 사용하고 있다. 최대한 npm으로 돌아가는 걸 찾아보고 싶었는데 없어서 그냥 다운받았다.

https://yarnpkg.com/lang/en/

git clone https://github.com/kitze/react-electron-example
cd react-electron-example
yarn
yarn start

하면 다음과 같은 창을 만날 수 있다!

어떤 원리로 돌아가는가 보았더니

mainWindow.loadURL(
    isDev
        ? "http://localhost:3000"
        : `file://${path.join(__dirname, "../build/index.html")}`
);

개발중에는 React와 마찬가지로 3000번 포트에 올려서 Electron도 그 화면을 보여주고 빌드시에는 React를 빌드하고 빌드된 화면으로 실행하는 듯

Electron : 이벤트

@baealex
2020-02-12 09:29(Last Update: 2020-02-18 10:13)

커스텀 이벤트를 만들어 보기 위해서 index.html에 다음과 같은 버튼을 추가하고 웹사이트를 만들때 처럼 직접 onclick을 넣었더니 오류가 발생했다.

<button onclick="btnClick()">click here</button>

무조건 다음과 같이 해야하나 보다.

<button id="mainButton">click here</button>
var mainButton = document.getElementById('mainButton')
mainButton.addEventListener('click', function() {
    alert('btn click!')
});

Electron : 통신

@baealex
2020-02-12 09:15(Last Update: 2020-02-18 10:13)

통신은 Main의 ipcMain과 Render의 ipcRenderer를 통해서 진행된다. 기존 튜토리얼에선 별다른 설정없이 Render에서 다음 라이브러리를 호출하는 것 같으나 상위 버전에선 불가능하여 찾아보니 BrowserWindow를 생성할 때 다음과 같은 Preferences를 생성해야 한다.

webPreferences: {
    nodeIntegration: true
}

이후 Main에서

const { ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg);
  event.sender.send('asynchronous-reply', 'pong')
})

Render에서

const { ipcRenderer } = require('electron')

ipcRenderer.send('asynchronous-message', 'ping')
ipcRenderer.on('asynchronous-reply', (event, arg) => {
    console.log(arg)
})

위와같이 통신을 진행한다.

Electron : 파일의 구성

@baealex
2020-02-12 09:12(Last Update: 2020-02-20 10:05)
  • main.js
    • 메인 프로세스
    • 데스크톱 앱의 백엔드 역할을 수행
    • 앱 자체의 총괄적인 부분(Node.js와 거의 동일)
    • 업데이트 제어
    • OS GUI API 제어(윈도우, 트레이, 메뉴, 컨텍스트 팝업)
  • renderer.js
    • 렌더러 프로세스
    • 데스크톱 앱의 프론트엔드 역할을 수행
    • 브라우저 화면, HTML/CSS/JS를 처리

Electron : 효과 넣기

@baealex
2020-02-12 09:09(Last Update: 2020-02-18 10:13)
notification 전송

renderer.js에 다음과 같은 내용 추가

let myNotification = new Notification('Title', {
    body: 'Lorem Ipsum Dolor Sit Amet'
})

myNotification.onclick = () => {
    console.info('Notification clicked')
}


prograss

BrowserWindow가 선언된 부분에서

mainWindow.setProgressBar(0.5)