How to cleanup useEffect callback?

Viewed 63

According to docs, one should use callbacks to communicate from main to renderer.

When using useEffect, how can one cleanup window.api.test using return function to prevent multiple instances of callback from being fired?

Looking for callback equivalent to addEventListener and removeEventListener model.

preload.ts

import { contextBridge, ipcRenderer } from "electron"

export interface API {
  test: (callback: () => void) => void
}

const api: API = {
  test: (callback) => {
    ipcRenderer.on("test", (event) => {
      callback()
    })
  },
}

contextBridge.exposeInMainWorld("api", api)

renderer.tsx

…
useEffect(() => {
  window.api.test(() => {
    console.log("test fired")
  })
  return () => {
    // Cleanup window.api.test somehow…
  }
}, [])
…
1 Answers

A common approach when adding event handlers is to return a function that can be used to remove it.

Unfortunately ipcRenderer.on() doesn't do this () but you can create your own

type ListenerCallback = () => void;
type Remover = () => void;

export interface API {
  test: (listener: ListenerCallback) => Remover;
}

const api: API = {
  test: (callback) => {
    const listener = (event: Event) => {
      callback();
    };

    ipcRenderer.on("test", listener);
    return () => {
      ipcRenderer.removeListener("test", listener);
    };
  },
};

Now your effect hook can use the return value in its cleanup

useEffect(() => {
  return window.api.test(() => {
    console.log("test fired");
  });
}, []);

See ipcRenderer.removeListener(channel, listener)

Related