Redux IPC abstraction layer that uses middleware to forward actions between the main and renderer processes.
- Node.js >= v22
- TypeScript >= v5
- Electron >= v30
Getting the library working is a three-step process:
- Set up the communication layer in a
preload
script. - Add Redial middleware to the Redux store in the main process
- Add Redial middleware to the Redux store in the renderer process
Note
The preload step was added to v4 to ensure the library is adhering to recommended
security practices
when using the ipcRenderer
API.
Import the preload script.
/** src/preload.js */
import "@laserware/redial/preload";
Call the createRedialMainMiddleware
function in your Redux store configuration code in the main process.
/** src/main.ts */
import { createRedialMainMiddleware } from "@laserware/redial/main";
import { configureStore, type Store } from "@reduxjs/toolkit";
import { app, BrowserWindow } from "electron";
import { rootReducer } from "../common/rootReducer";
function createStore(): Store {
const redialMiddleware = createRedialMainMiddleware();
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(redialMiddleware),
});
app.on("before-quit", () => {
// Perform cleanup:
redialMiddleware.dispose();
});
}
function createWindow(): void {
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true,
// Assuming the preload script is in the same directory
// as the `main` file output:
preload: join(__dirname, "preload.js"),
},
});
}
async function start(): Promise<void> {
await app.whenReady();
createStore();
createWindow();
}
start();
Call the createRedialRendererMiddleware
in your Redux store configuration code in the renderer process.
/** src/renderer.ts */
import { createRedialRendererMiddleware } from "@laserware/redial/renderer";
import { configureStore, type Store } from "@reduxjs/toolkit";
import { rootReducer } from "../common/rootReducer";
export function createStore(): Store {
const redialMiddleware = createRedialRendererMiddleware();
let preloadedState;
// If using Vite:
if (import.meta.env.MODE === "development") {
preloadedState = redialMiddleware.getMainStateSync();
}
const store = configureStore({
preloadedState,
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(redialMiddleware),
});
}
The API was completely changed in version 3 to use a single middleware import with methods, rather than returning the store from an initializer function (withRedial
).
If you want to request the current state from the main process, the return value of createRedialRendererMiddleware
provides two methods:
getMainState
, which is asynchronousgetMainStateSync
, which is synchronous (and blocking!)
export function createStore() {
const redialMiddleware = createRedialRendererMiddleware();
const stateFromMain = redialMiddleware.getMainStateSync();
}
In the main process, listeners are automatically added to return the state when requested.
The preload step was added in version 4 to adhere to recommended security practices when using the ipcRenderer
API.
You must now call exposeRedialInMainWorld
in a preload script and load that script when creating a BrowserWindow
.
See the Usage instructions above for additional information.
The exported preload function was renamed from exposeRedialInMainWorld
to preloadRedial
.
/** src/preload.js */
/* Before */
import { exposeRedialInMainWorld } from "@laserware/redial/preload";
/* After */
import { preloadRedial } from "@laserware/redial/preload";
// Set up the communication layer between the main and renderer processes:
/* Before */
exposeRedialInMainWorld();
/* After */
preloadRedial();
The preload file was changed to a side-effect import.
/** src/preload.js */
/* Before */
import { preloadRedial } from "@laserware/redial/preload";
preloadRedial();
/* After */
import "@laserware/redial/preload";