sindresorhus / electron-store

Simple data persistence for your Electron app or module - Save and load user preferences, app state, cache, etc
MIT License
4.61k stars 150 forks source link

Issues with .onDidChange() and .onDidAnyChange() #187

Closed KookiKodes closed 3 years ago

KookiKodes commented 3 years ago

Hello, I just wanted to start off saying that this tool is amazing! Unfortunately however, I have come across and error, the error being when I'm using the store within the preload file of my electron app. I've tested these functions on the the electron side and it works great. Essentially I want to be able to update the front-end of my application whenever data from the store changes, I've directly imported the store into the preload file and setup the event listener within the front-end as well. Unfortunately whenever the data changes within the store it does not fire the callback from the data changing. Here is an example of my code. Also thank you ahead of time for reviewing this :) ! Oh and to note, the preload.ts file was made available within the BrowserWindow obj.

preload.ts file

import { contextBridge } from "electron";
import { ipcRenderer } from "electron-better-ipc";
import { Application } from "./Models/Application";

function onDidAnyChange(cb: (newValue, oldValue) => void) {
    Application.webData.onDidAnyChange(cb); //The application has the store labeled as "webData" attached statically"
  }

contextBridge.exposeInMainWorld('fileHandler', {
 onDidAnyChange,
})

fileHandler.ts file

export const onDidAnyChange = (cb: (newValue: any, oldValue: any) => void) => {
  (window as any).fileHandler.onDidAnyChange(cb);
}

App.svelte file

<script lang="ts">
  import "./styles/global.css";
  import LineNumbers from "./LineNumbers/index.svelte";
  import { onDidAnyChange, updateFileContents, getFileContents } from "./fileHandler";

  $: content = getFileContents();
  $: lineNums = content.split(/\r\n|\r|\n/).length;

  onDidAnyChange((newVal, oldVal) => {
    console.log(newVal, oldVal);
  });
</script>

<main>
  <LineNumbers lineNums="{lineNums}" />
  <textarea bind:value="{content}"></textarea>
</main>
KookiKodes commented 3 years ago

I was able to find a solution, as I realized that I should communicate using the ipcRenderer and ipcMain. I am very pleased with your electron-better-ipc package. So I updated my code with the following :).

preload.ts

import { contextBridge } from "electron";
import { ipcRenderer } from "electron-better-ipc";
import { Application } from "./Models/Application";

function onDidAnyChange(cb: (data) => void) {
    ipcRenderer.answerMain("on-did-any-change", (data) => {
      cb(data);
    });
  }

contextBridge.exposeInMainWorld('api', {
  onDidAnyChange,
})

Application.ts

Application.webData.onDidAnyChange((newValue, oldValue) => {
    ipcMain.callFocusedRenderer("on-did-any-change", { newValue, oldValue });
});

fileHandler.ts

export const onDidAnyChange = (cb: (data: any) => void) => {
  (window as any).fileHandler.onDidAnyChange(cb);
}

App.svelte

<script lang="ts">
  import "./styles/global.css";
  import LineNumbers from "./LineNumbers/index.svelte";
  import { onDidAnyChange, updateFileContents, getFileContents } from "./fileHandler";

  $: content = getFileContents();
  $: lineNums = content.split(/\r\n|\r|\n/).length;

  onDidAnyChange((data) => {
    console.log(data);
  });
</script>

<main>
  <LineNumbers lineNums="{lineNums}" />
  <textarea bind:value="{content}"></textarea>
</main>

Again thank you for these amazing tools, it has made the development process soooo much easier! I'm closing this comment as this work around solution worked and I hope it helps future people using this package as well 👍 !