みかづきメモ

学習したことのメモとか、日記とか、備忘録。

React で Electron の WebView を使いたい

Electron + React で開発してて、 WebView を使いたいってことがあったけど、
普通に追加するだけだったら駄目だったので、やり方のメモ。


結論としては、 React.createElement で埋め込むんじゃなく、 DOM 操作で追加しました。
ネット上の過去の記事をみると、 <webview src="..." autosize /> としてるけども、
少なくとも 15.4.1 時点では警告がでます。

実装は下の通り。
イベント周りもちゃんとすべきですが、私は表示さえできればよかったので、実装していません。

/// <reference path="../typings/index.d.ts" />

// Electron <webview> wrapper for React.
import * as React from "react";
import * as ReactDOM from "react-dom";

export interface IWebViewProps {
  src: string;
  autosize?: boolean;
  nodeintegration?: boolean;
  plugins?: boolean;
  preload?: string;
  httpreferrer?: string;
  useragent?: string;
  disablewebsecurity?: boolean;
  partition?: string;
  allowpopups?: boolean;
  webpreferences?: string;
  blinkfeatures?: string;
  disableblinkfeatures?: string;
  guestinstance?: string;
  disableguestresize?: boolean;
}

export class WebView extends React.Component<IWebViewProps, void> {
  private element: HTMLDivElement;

  public componentDidMount(): void {
    const container = ReactDOM.findDOMNode(this.element);
    let props = "";
    for (let prop in this.props) {
      if (prop === "className") {
        props += `class="${this.props[prop]}" `;
      } else {
        if (typeof this.props[prop] === "boolean") {
          props += `${prop}="${(this.props[prop] ? 'on' : 'off')}" `;
        } else {
          props += `${prop}="${this.props[prop]}" `;
        }
      }
    }
    container.innerHTML = `<webview ${props} />`;
    const webview: Electron.WebViewElement = container.querySelector("webview") as Electron.WebViewElement;
    webview.addEventListener("dom-ready", (w) => {
      if (process.env === "development") {
        if (!webview.isDevToolsOpened()) {
          webview.openDevTools();
        }
      }
    });
  }

  public render(): JSX.Element {
    return (
      <div ref={(w) => this.element = w} />
    );
  }
}

おわり。