electron 观察在电子中添加或删除文件时React和更新状态的变化

1l5u6lss  于 2023-01-22  发布在  Electron
关注(0)|答案(1)|浏览(148)

我正在开发一个前端使用React的电子应用程序。该应用程序将显示几个文件夹中的文件。然后它将允许用户使用一些按钮删除文件或将文件复制到另一个文件夹。我已经知道如何使用按钮删除或复制文件。但我不知道如何在删除或复制文件后更新GUI。我一直在遵循以下教程:https://medium.com/jspoint/working-with-files-i-o-in-an-electron-application-b4d2de403f54
下面是我的后端electron.js的相关部分:

// Module to control the application lifecycle and the native browser window.
const {
  app,
  BrowserWindow,
  protocol,
  nativeTheme,
  ipcMain,
} = require("electron");
const path = require("path");
const url = require("url");

const io = require("../electron/io");

// Create the native browser window.
function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    autoHideMenuBar: true,
    resizable: false,
    // Set the path of an additional "preload" script that can be used to
    // communicate between node-land and browser-land.
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
    },
  });

  nativeTheme.themeSource = "dark";

  // return list of current front end files
  ipcMain.handle("app:get-current-FE-files", () => {
    return io.getFiles("C:/test");
  });

  // return list of previous front end files
  ipcMain.handle("app:get-previous-FE-files", () => {
    return io.getFiles("C:/test-previous-files");
  });

  ipcMain.handle("app:delete-all-folder-contents", (event, folder) => {
    // console.log({ event });
    // console.log({ folder });
    let folderWithFiles = '';
    if (folder === 'prodorchtest-previous-folder') {
      folderWithFiles = 'C:/test-previous-files';
    }
    return io.deleteAllFilesInFolder(folderWithFiles);
  });

  ipcMain.handle("app:copy-all-folder-contents", (event, fromTo) => {
    console.log({ fromTo })
    if (fromTo === 'prodorchtest-to-previous-folder') {
      return io.copyFilesBetweenFolders('C:/test', 'C:/test-previous-files');
    }
  });

  // In production, set the initial browser path to the local bundle generated
  // by the Create React App build process.
  // In development, set it to localhost to allow live/hot-reloading.
  const appURL = app.isPackaged
    ? url.format({
        pathname: path.join(__dirname, "index.html"),
        protocol: "file:",
        slashes: true,
      })
    : "http://localhost:3006";
  mainWindow.loadURL(appURL);

  io.watchFiles(mainWindow);

io.js中,watchFiles是这样的:

// watch files from the application's storage directory
exports.watchFiles = (win) => {
  const prevFEFolder = 'C:/test-previous-files';

  // chokidar.watch(prevFEFolder).on("unlink", (filepath) => {
  //   console.log('unlink called with: ', filepath)
  //   //win.webContents.send("app:delete-file", path.parse(filepath).base);
  // });
  chokidar.watch(prevFEFolder).on('add', (path) => {
    console.log({ path });
    win.webContents.send("app:add-file", path);
  });
};

下面是我的preload.js

// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
const { contextBridge, ipcRenderer } = require("electron");

// As an example, here we use the exposeInMainWorld API to expose the browsers
// and node versions to the main window.
// They'll be accessible at "window.versions".
process.once("loaded", () => {
  contextBridge.exposeInMainWorld("versions", process.versions);
});

contextBridge.exposeInMainWorld("fsInfo", {
  getCurrentFEDirContents: () => ipcRenderer.invoke("app:get-current-FE-files"),
  getPreviousFEDirContents: () =>
    ipcRenderer.invoke("app:get-previous-FE-files"),
});

contextBridge.exposeInMainWorld("fsActions", {
  deleteAllFolderContents: (folder) => ipcRenderer.invoke("app:delete-all-folder-contents", folder),
  copyAllFolderContents: (fromTo) => ipcRenderer.invoke("app:copy-all-folder-contents", fromTo),
});

我不确定我是否应该在那里添加前端功能来监视文件更改,或者它是否应该在App.js中。
这是我的App.js的第一部分:

import React, { useEffect, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowRight, faFileImage } from '@fortawesome/free-solid-svg-icons';
import folder from './img/folder.png';
import ErrorBoundary from './ErrorBoundary';

// this import causes errors
// const { ipcRenderer } = require('electron');

const App = () => {
  // these state arrays are what I would want to update when changes are made with deleting
  // or copying files
  const [currentFEFiles, setCurrentFEFiles] = useState([]);
  const [previousFEFiles, setPreviousFEFiles] = useState([]);

  // useEffect(() => {

  //   // Listen for the event
  //   ipcRenderer.on('app:add-file', (event, arg) => {
  //     console.log({event, arg})
  //   });

  //   // Clean the listener after the component is dismounted
  //   return () => {
  //     ipcRenderer.removeAllListeners();
  //   };

  // }, []);

  const getTheFiles = async () => {
    try {
      const currentFilelist = await window.fsInfo.getCurrentFEDirContents();
      console.log({ currentFilelist });
      currentFilelist.sort((a, b) =>
        a.isDir < b.isDir ? 1 : b.isDir < a.isDir ? -1 : a.name - b.name
      );
      setCurrentFEFiles(currentFilelist);

      const previousFileList = await window.fsInfo.getPreviousFEDirContents();
      previousFileList.sort((a, b) =>
        a.isDir < b.isDir ? 1 : b.isDir < a.isDir ? -1 : a.name - b.name
      );
      setPreviousFEFiles(previousFileList);
    } catch (e) {
      console.log({ e });
      setCurrentFEFiles([]);
    }
    // setCurrentFEFiles([]);
  };

  useEffect(() => {
    getTheFiles();
    //window.fsInfo.getDirContents().then(r => console.log({r}));
    // console.log({ filelist });
  }, []);

  const deleteFolderContents = async (folder) => {
    await window.fsActions.deleteAllFolderContents(folder);
  };

  const copyFolderContents = async (fromTo) => {
    await window.fsActions.copyAllFolderContents(fromTo);
    // maybe this is where I would add some code to update the state?
  };
mxg2im7a

mxg2im7a1#

问题应该只出在React部分。
在检查您的代码App.js后,似乎您的代码没有通知React在文件更改后重新渲染。
这里的useEffect

useEffect(() => {
    getTheFiles();
    //window.fsInfo.getDirContents().then(r => console.log({r}));
    // console.log({ filelist });
  }, []); // '[]' here means run only once

只运行一次。它不会在每次更改文件时刷新用户界面。
即使在getTheFiles中更改了状态数组,getTheFiles也没有机会重新调用。
您可以尝试在await行下方的deleteFolderContentscopyFolderContents中添加getTheFiles(),因为getTheFiles中的setXXX将触发UI重新呈现。

const deleteFolderContents = async (folder) => {
    await window.fsActions.deleteAllFolderContents(folder);
    getTheFiles();
  };

  const copyFolderContents = async (fromTo) => {
    await window.fsActions.copyAllFolderContents(fromTo);
    getTheFiles();
  };

相关问题