Wails で Go → JS にデータを送る方法 (emit)

はじめに

この記事は Qiita Advent Calendar 2025 "Go シリーズ 2"20日目の記事です。

参考資料

shinshin86.hateblo.jp

↑ ぶっちゃけ上に全部書いてます。

wails.io

本文

Wails で Go から JS にデータを送るには、Go 側では runtime.EventsEmit を使い、JS側では EventsOn を使います。

// app.go
func (a *App) startup(ctx context.Context) {
    a.ctx = ctx

    go func() {
        // 1秒ごとに現在時刻を送信する
        for {
            ct := time.Now().Format("15:04:05")
            runtime.EventsEmit(a.ctx, "current_time", ct)
            <-time.After(1 * time.Second)
        }
    }()
}
// frontend/src/App.jsx
import { useEffect, useState } from "react";
import logo from "./assets/images/logo-universal.png";
import "./App.css";
import { Greet } from "../wailsjs/go/main/App";
import { EventsOn, EventsOff } from "../wailsjs/runtime/runtime";

function App() {
  const [resultText, setResultText] = useState(
    "Please enter your name below 👇"
  );
  const [name, setName] = useState("");
  const [currentTime, setCurrentTime] = useState("");
  const updateName = (e) => setName(e.target.value);
  const updateResultText = (result) => setResultText(result);

  // ここがキモ
  useEffect(() => {
    EventsOn("current_time", (msg) => {
      setCurrentTime(msg);
    });

    return () => {
      EventsOff("current_time");
      console.log("unmounting...");
    };
  });

  function greet() {
    Greet(name).then(updateResultText);
  }

  return (
    <div id="App">
      <img src={logo} id="logo" alt="logo" />
      <div id="result" className="result">
        {currentTime}
      </div>
      <div id="result" className="result">
        {resultText}
      </div>
      <div id="input" className="input-box">
        <input
          id="name"
          className="input"
          onChange={updateName}
          autoComplete="off"
          name="input"
          type="text"
        />
        <button className="btn" onClick={greet}>
          Greet
        </button>
      </div>
    </div>
  );
}

export default App;

これで、現在時刻を 1秒周期でJSに送ることができます。1ms周期でも動くには動きますが、重くなるのでやめておいた方がいいかもしれません。ご利用は計画的に。