role

Function: Encapsulate the IPC communication function of electron into a component form. When receiving the IPC message from the host process, the data in store in redux will be automatically updated. When the user changes the store in a special way, the store will be automatically updated and the message will be sent to the main process. The advantage of this is that some of the presentation class information does not need to register events frequently, just the component binding store can be done. Example:

// An example
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router';
import type { Store } from '.. /reducers/types';
import Routes from '.. /Routes';
import { ConnectIPC } from '.. /components/ConnectIPC';

export default function Root(Props) {
	const { store, history } = Props;
	return (
		<Provider store={store}>// The component needs to be wrapped in a reduxProvider that connects IPC to Redux<ConnectIPC>
				<ConnectedRouter history={history}>
					<Routes />
				</ConnectedRouter>
			</ConnectIPC>
		</Provider>
	);
}
Copy the code

implementation

ConnectedRouter: In ConnectIPC, we subscribe to the ipcRenderer event to get messages from the main process, and subscribe to the Store in Redux to get data sent by the user. 1. How to obtain store into ConnectIPC? React provides a provider pattern, which can be used as follows:

import { createContext } from 'react';

let { Provider, Consumer } = createContext();
// Child components wrapped by IPCProvider can get values using the Render props mode of IPCConsumer
export let IPCProvider = Provider;
export let IPCConsumer = Consumer;
Copy the code

Redux offers a similar approach

// Get the provider context of Redux in this way
import { ReactReduxContext } from 'react-redux';
Copy the code

Inject the Store into the component

	function ConnectIPCWithContext(props) {
		let Context = props.context || ReactReduxContext;
		if (Context == null) {
			throw 'Please upgrade to react-redux v6';
		}
		return<Context.Consumer>{({ store }) => <ConnectIPC store={store} {... props} />}</Context.Consumer>; }Copy the code

2, How to implement the child component is wrapped by ConnectIPC, and implement the listening change state

class ConnectIPC extends Component { constructor(props) { super(props); // Get the store onIPCRenderMessage injected by the ConnectIPCWithContext component above. The Action method injected by the Connect component of react-redux. let { store, onIPCRenderMessage, children } = props; The wrapIpcRender method registers the event and returns the cancel event method, which can be unregistered during component life cycle uninstallation. This. UnipcRender = wrapIpcRender((event, arg) => {// Accept message onIPCRenderMessage(arg); }); this.lastSendMsg = {}; // When the user sends data to the main process, it should also be through the store operation. In order to prevent the data from being sent repeatedly, each time the data is guaranteed to be unique by the UUID. Subscribe = store. Subscribe (() => {console.log(' listen ') let {sendMsg} = store.getState(); // if (this.lastsendmsg. uuid === sendmsg. uuid) {// return; Ipcrenderer. send('channel', sendMsg); // this.lastSendMsg = sendMsg; }); SendIPCRenderMessage is an action, This. WrapIpcRendererMsg = wrapIpcRendererMsg(Store, sendIPCRenderMessage); } // componentWillUnmount() {this.unipcrender (); this.unSubScribe(); } render() { let { children } = this.props; <IPCProvider value={{sendIpcRendererMsg: This. WrapIpcRendererMsg}}> // ensure that the child component is unique {react.children. Only (Children)} </IPCProvider>); Import {ipcRenderer} from 'electron' export function wrapIpcRender(cb){import {ipcRenderer} from 'electron' export function wrapIpcRender(cb){ ipcRenderer.on('channel',cb); return function(){ ipcRenderer.removeListener('channel',cb); } export function wrapIpcRendererMsg(store,action){ // ipcRenderer.send(msg) return (args)=>{ // console.log( ${json.stringify (store.getState())} ') store.dispatch(action(args)); }}Copy the code

How to inject the sendIpcRendererMsg method into the required components? Using a higher-order component like Redux’s Connect, the bonus point is that the ES6 class decorator function that returns a value other than false will use that value when calling the class. Below is the implementation and use of injection

/ / implementation
export function connectIPCSender() {
	return (Component) = > (props) => (
	// Get the provider's data using IPC
		<IPCConsumer>
		// Pass the method to the child component, but the higher-order component rules ensure that the props are passed, so you need to pass the props
			{({ sendIpcRendererMsg }) => <Component sendIpcRendererMsg={sendIpcRendererMsg} {. props} / >}
		</IPCConsumer>
	);
}
// Use the sendIpcRendererMsg method to inject a title bar@connectipcSender ()export default class Heade extends Component{
  render(){
    console.log(this.props)
    let {sendIpcRendererMsg}=this.props;
    return (
      <div onClick={()= >{console.log('dianji'); sendIpcRendererMsg(Date.now())}} className={styles.heade}>

      </div>)}}Copy the code

Conceptual things

The main concepts used in React documentation are: (1) High-order components (2) Render Props (3) Provider mode (4) Function creationization