redux-persist-electron-storage
redux-persist-electron-storage copied to clipboard
Not loading page after reload
I want to use redux-persist-electron-storage to store some project data. I set everything up according to the instructions. To begin with, the application started to run for a very long time. Secondly, if you refresh the page in electron, then it does not load the page, just a white screen hangs. This does not open dev-tools, that is, it feels like the application has entered a loop somewhere. Is there any way to solve this problem?
store configuration
import { configureStore } from "@reduxjs/toolkit";
import ElectronStore from "electron-store";
import createElectronStorage from "redux-persist-electron-storage";
import persistStore from "redux-persist/es/persistStore";
import thunk from "redux-thunk";
import promise from "redux-promise-middleware";
import { persistReducer } from "redux-persist";
import { app } from "@electron/remote";
import tableReducer from "./table/tableReducer";
import sidebarMenuReducer from "./sidebarMenu/sidebarMenuReducer";
import electronCacheReducer from "./electronCache/electronCacheReducer";
export const electronStore = new ElectronStore({ cwd: app.getPath("userData") });
const electronCachePersistConfig = {
key: "electronCache",
storage: createElectronStorage({ electronStore })
};
const electronCachePersistedReducer = persistReducer(electronCachePersistConfig, electronCacheReducer);
export const store = configureStore({
reducer: {
tableData: tableReducer,
sidebarMenu: sidebarMenuReducer,
electronCache: electronCachePersistedReducer
},
devTools: process.env.NODE_ENV !== "production",
middleware: [promise, thunk]
});
/* // @ts-ignore
module.hot.accept("./electronCache/electronCacheReducer", () => {
// This fetch the new state of the above reducers.
// @ts-ignore
const nextElectronCacheReducer = require("./electronCache/electronCacheReducer").default;
// @ts-ignore
store.replaceReducer(
{
// @ts-ignore
tableData: tableReducer,
sidebarMenu: sidebarMenuReducer,
electronCache: persistReducer(electronCachePersistConfig, nextElectronCacheReducer)
}
);
}); */
export const persistor = persistStore(store);
persistor.persist();
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
index.tsx
import * as React from "react";
import { render } from "react-dom";
import "./styles/globals.scss";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { Loader } from "semantic-ui-react";
import { persistor, store } from "./store";
import App from "./components/App";
import partsStyles from "./styles/parts.scss";
render((
<Provider store={store}>
<PersistGate
loading={(
<div className={partsStyles.loaderContainer}>
<Loader active inline="centered" />
</div>
)} persistor={persistor}
>
<App />
</PersistGate>
</Provider>
), document.querySelector("#app"));
webpack config for renderer
import path from "path";
import webpack, { Configuration } from "webpack";
import HtmlWebpackPlugin from "html-webpack-plugin";
import { CleanWebpackPlugin } from "clean-webpack-plugin";
import { merge } from "webpack-merge";
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import createElectronReloadWebpackPlugin from "electron-reload-webpack-plugin";
export const PATHS = {
src: path.join(__dirname, "./src"),
dist: path.join(__dirname, "./app/dist"),
global: path.resolve(__dirname, "./src/styles/globals.scss"),
assets: "assets/",
nodeModules: path.resolve(__dirname, "./node_modules"),
app: path.resolve(__dirname, "./app")
};
const isProduction = process.env.NODE_ENV === "production";
const mode = isProduction ? "production" : "development";
module.exports = () => {
const commonPlugins = [
new HtmlWebpackPlugin({
template: `${PATHS.src}/index.html`,
filename: "./index.html",
title: "Demo",
publicPath: isProduction ? "./" : ""
}),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: []
}),
new webpack.ProgressPlugin(),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(mode),
"process.env.DEBUG": JSON.stringify(process.env.DEBUG)
}),
new ForkTsCheckerWebpackPlugin()
];
const devPlugins = [
new webpack.SourceMapDevToolPlugin({
filename: "[file].map"
}),
createElectronReloadWebpackPlugin()()
];
const plugins = [...commonPlugins, ...(isProduction
? []
: devPlugins)];
const devOptions: Configuration = {
devServer: {
contentBase: PATHS.dist,
port: 8085,
overlay: {
warnings: false,
errors: true
},
hot: true,
historyApiFallback: true
}
};
const config: Configuration = {
mode,
target: "electron-renderer",
devtool: isProduction ? "cheap-source-map" : "eval-cheap-module-source-map",
context: __dirname,
entry: {
app: PATHS.src
},
resolve: {
extensions: [".js", ".jsx", ".ts", ".tsx", "json", ".css", ".scss", ".svg", ".ignore"]
},
module: {
rules: [{
test: /\.scss$/,
include: [PATHS.global],
use: ["style-loader", "css-loader", "sass-loader"]
}, {
test: /\.scss$/,
exclude: [/node_modules/, PATHS.global],
use: [
"style-loader", {
loader: "css-loader",
options: {
import: true,
sourceMap: true,
modules: {
mode: "local",
localIdentName: "[path][name]__[local]--[hash]",
exportLocalsConvention: "camelCaseOnly"
}
}
}, {
loader: "postcss-loader",
options: {
sourceMap: true,
postcssOptions: {
config: path.resolve(__dirname, "postcss.config.js")
}
}
}, {
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
}, {
test: /\.tsx?$/,
exclude: [PATHS.nodeModules, PATHS.app],
use:
[{
loader: "ts-loader",
options: {
compilerOptions: {
module: "ESNext",
removeComments: false
}
}
}]
}, {
test: /\.(ignore|zip|png|ttf|otf|eot|svg|woff(2)?)(\?[\da-z]+)?$/,
use:
[{
loader: "file-loader",
options: {
name: "[name]-[contenthash].[ext]",
outputPath: "static/assets/"
}
}]
}]
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
name: "vendors",
test: /node_modules/,
chunks: "all",
enforce: true,
maxSize: 249_856
}
}
},
runtimeChunk: "single",
moduleIds: "deterministic"
},
output: {
path: PATHS.dist,
filename: `${PATHS.assets}js/[name]-bundle.[fullhash].js`,
publicPath: isProduction ? "./" : "/"
},
plugins
};
return isProduction ? config : merge(config, devOptions);
};
webpack config for main
import path from "path";
export const PATHS = {
electronMain: path.join(__dirname, "./app/main.ts"),
dist: path.join(__dirname, "./app/dist")
};
const isProduction = process.env.NODE_ENV === "production";
const mode = isProduction ? "production" : "development";
module.exports = {
mode,
target: "electron-main",
entry: {
app: PATHS.electronMain
},
resolve: {
extensions: [".js", ".ts"]
},
module: {
rules: [
{
test: /app\/main\.ts$/,
include: PATHS.electronMain,
use:
[{
loader: "ts-loader",
options: {
compilerOptions: {
module: "commonjs",
removeComments: true
}
}
}]
}
]
},
output: {
path: PATHS.dist,
filename: "main.js",
publicPath: "/"
}
};
main.ts
import electron from "electron";
import isElectronDev from "electron-is-dev";
import installExtension, { REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } from "electron-devtools-installer";
import { client } from "electron-connect";
import { initialize as remoteInitialize } from "@electron/remote/main";
const {
app,
BrowserWindow,
Menu
} = electron;
if (!isElectronDev) {
app.on("browser-window-created", (e, window) => {
if (process.platform === "darwin") {
window.setMenu(Menu.buildFromTemplate([{ // иначе не работает CmdC, CmdV, CmdX
label: "Edit",
submenu: [
{
label: "Cut",
accelerator: "CmdOrCtrl+X"
},
{
label: "Copy",
accelerator: "CmdOrCtrl+C"
},
{
label: "Paste",
accelerator: "CmdOrCtrl+V"
}
]
}]));
} else {
window.setMenu(null);
}
});
}
function loadMain() {
const screenWidth = electron.screen.getPrimaryDisplay().size.width;
const screenHeight = electron.screen.getPrimaryDisplay().size.height;
remoteInitialize();
const mainWindow = new BrowserWindow({
width: 1366,
height: 768,
minWidth: 1366,
minHeight: 768,
show: false,
webPreferences: {
devTools: isElectronDev,
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}
});
mainWindow.loadURL(isElectronDev ? "http://localhost:8085" : `file://${__dirname}/index.html`);
mainWindow.once("ready-to-show", () => {
if (isElectronDev) {
client.create(mainWindow);
}
mainWindow.show();
});
if (screenWidth === 1366 && screenHeight === 768) {
mainWindow.maximize();
mainWindow.setResizable(false);
} else {
mainWindow.setResizable(true);
}
mainWindow.webContents.setWindowOpenHandler(() => ({ action: "deny" }));
function close() {
app.quit();
}
mainWindow.once("close", close);
}
app.on("window-all-closed", () => {
app.quit();
});
app.on("quit", () => {
app.quit();
});
app.whenReady()
.then(() => {
if (isElectronDev) {
installExtension(REACT_DEVELOPER_TOOLS)
.then((name) => console.log(`Added Extension: ${name}`))
.catch((error) => console.log("An error occurred:", error));
installExtension(REDUX_DEVTOOLS)
.then((name) => console.log(`Added Extension: ${name}`))
.catch((error) => console.log("An error occurred:", error));
}
loadMain();
});
I am use
- react - "17.0.2"
- react-redux - "7.2.4"
- redux-persist - "6.0.0",
- redux-persist-electron-storage - 2.1.0
- electron - 13.1.3
- webpack - 5.38.1
- electron-store - 8.0.0