redux-persist 不在电子应用程序中工作
redux-persist not working in electron app
我正在尝试将 redux-persist
与我的电子应用程序一起使用,但状态不会持续存在。我不确定我做错了什么。当我 CMD+R 状态被重置。当完全构建的应用程序退出并重新启动时,状态也会重置。
我的 electron 应用程序是用 react + redux 制作的,并与 webpack 捆绑在一起。
store.js
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
import { persistStore, persistCombineReducers } from 'redux-persist'; //persistReducer
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
import autoMergeLevel1 from 'redux-persist/lib/stateReconciler/autoMergeLevel1';
const persistConfig = {
key : 'primary',
storage,
stateReconciler: autoMergeLevel1
};
const persistedReducer = persistCombineReducers(persistConfig, rootReducer);
const actionSanitizer = (action) => (
action.type === 'ADD_FILE' && action.libraryEntry ?
{ ...action,
libraryEntry: {
artwork: '<<LARGE_ARTWORK_BUFFER>>'
}
} : action
);
const composeEnhancers =
typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
name : 'Melo',
actionSanitizer,
stateSanitizer: (state) => state.library.files ? {
...state, library: {
files: '<<LONG_LIST_OF_FILES>>'
}
} : state
})
: compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk)
);
const configureStore = (initialState) => {
const store = createStore(persistedReducer, initialState, enhancer);
const persistor = persistStore(store);
return { store, persistor };
};
export default configureStore;
每个减速器定义为:
import * as constants from '../../constants/settings';
const ACTION_HANDLERS = {
[constants.SET_ERROR_REPORTING]: (state, { allowReporting }) => {
return {
...state,
error: {
allowReporting
}
};
},
[constants.SET_ERROR_MODAL]: (state, { allowErrorModal }) => {
return {
...state,
error: {
allowErrorModal
}
};
},
[constants.DISABLE_ERROR_REPORTING]: (state) => {
return {
...state,
error: {
allowReporting: false
}
};
}
};
export const initialState = {
error: {
allowReporting : false,
allowErrorModal: true
}
};
const settingsReducer = (state = initialState, action) => {
const handler = ACTION_HANDLERS[action.type];
return handler ? handler(state, action) : state;
};
export default settingsReducer;
rootReducer 在此处导出:
import library from './library';
import player from './player';
import view from './view';
import settings from './settings';
export default {
library,
player,
view,
settings
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BarLoader } from 'react-spinners';
import { PersistGate } from 'redux-persist/integration/react';
import configureStore from './store';
import MainView from './app';
import './styles/global.scss';
const { store, persistor } = configureStore({});
const loading = <BarLoader color={'#3E8BD3'} size={25}/>;
require('dotenv').config();
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={loading} persistor={persistor}>
<MainView/>
</PersistGate>
</Provider>,
document.getElementById('root')
);
我在 redux-persist
github 个问题 here 中做了 post 个问题。几年前有几个线程针对这个特定问题,但这些解决方案对我不起作用。感谢您提供的所有帮助!
更新:
我在第一个答案中实施了建议 但我仍然看到相同的行为
编辑:我写得太快了,没有足够的思考。这个连看都不看
我可能是错的,但我认为您的商店应该在 store.js
文件中创建一次。
阅读这一行,我猜你每次重新加载或启动你的应用程序时都会创建一个新商店,这会使你丢失持久数据:
const { store, persistor } = configureStore({});
您最好在 store.js
文件中导出您的商店:
...
const store = createStore(persistedReducer, initialState, enhancer);
const persistor = persistStore(store);
export {
store,
persistor
}
然后将您的商店导入 App.js
文件:
import { store, persistor } from './store'
希望对您有所帮助
问题是我的 webpack 配置不正确,我的代码是 运行 没有正确设置的旧版本。这是使我能够正常工作的最终文件!
src/store/index.js
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
import { persistStore, persistCombineReducers } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel1 from 'redux-persist/lib/stateReconciler/autoMergeLevel1';
import logger from 'redux-logger';
const persistConfig = {
key : 'primary',
storage,
stateReconciler: autoMergeLevel1
};
const persistedReducer = persistCombineReducers(persistConfig, rootReducer);
const actionSanitizer = (action) => (
action.type === 'ADD_FILE' && action.libraryEntry ?
{ ...action,
libraryEntry: {
artwork: '<<LARGE_ARTWORK_BUFFER>>'
}
} : action
);
const composeEnhancers =
typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
name : 'Melo',
actionSanitizer,
stateSanitizer: (state) => state.library.files ? {
...state, library: {
files: '<<LONG_LIST_OF_FILES>>'
}
} : state
})
: compose;
const middlewares = [thunk, logger];
const enhancer = composeEnhancers(
applyMiddleware(...middlewares)
);
const reduxStore = createStore(persistedReducer, {}, enhancer);
const persistor = persistStore(reduxStore);
const store = { reduxStore, persistor };
export default store;
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BarLoader } from 'react-spinners';
import { PersistGate } from 'redux-persist/integration/react';
import MainView from './app';
import registerServiceWorker from './registerServiceWorker';
import './styles/global.scss';
import store from './store';
const { reduxStore, persistor } = store;
registerServiceWorker();
const loading = <BarLoader color={'#3E8BD3'} size={25}/>;
require('dotenv').config();
ReactDOM.render(
<Provider store={reduxStore}>
<PersistGate loading={loading} persistor={persistor}>
<MainView/>
</PersistGate>
</Provider>,
document.getElementById('root')
);
src/reducers/index.js
import library from './library';
import player from './player';
import view from './view';
import settings from './settings';
export default {
library,
player,
view,
settings
};
webpack.config.js
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { spawn } = require('child_process');
// Config directories
const SRC_DIR = path.resolve(__dirname, 'src');
const OUTPUT_DIR = path.resolve(__dirname, './build');
// Any directories you will be adding code/files into, need to be
// added to this array so webpack will pick them up
const defaultInclude = [SRC_DIR];
module.exports = {
entry : `${SRC_DIR}/index.js`,
mode : 'development',
output: {
path : OUTPUT_DIR,
publicPath: path.join('./'),
filename : 'bundle.js'
},
module: {
rules: [
{
test: /\.(s*)css$/,
use : [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test : /\.js$/,
exclude: /node_modules(?!(\/|\)js-utils)/,
loader : 'babel-loader'
},
{
test : /\.jsx$/,
exclude: /node_modules(?!(\/|\)js-utils)/,
loader : 'babel-loader'
},
{
test : /\.(jpe?g|png|gif)$/,
use : [{ loader: 'file-loader?name=img/[name]__[hash:base64:5].[ext]' }],
include: defaultInclude
},
{
test : /\.(eot|svg|ttf|woff|woff2)$/,
use : [{ loader: 'file-loader?name=font/[name]__[hash:base64:5].[ext]' }],
include: defaultInclude
}
]
},
target : 'electron-renderer',
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject : 'body'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
],
devtool : 'cheap-source-map',
devServer: {
contentBase: OUTPUT_DIR,
stats : {
colors : true,
chunks : false,
children: false
},
before() {
spawn(
'electron',
['./public/electron.js'],
{ shell: true, env: process.env, stdio: 'inherit' }
)
.on('close', code => process.exit(0))
.on('error', spawnError => console.error(spawnError));
}
}
};
感谢所有帮助过我的人!
我正在尝试将 redux-persist
与我的电子应用程序一起使用,但状态不会持续存在。我不确定我做错了什么。当我 CMD+R 状态被重置。当完全构建的应用程序退出并重新启动时,状态也会重置。
我的 electron 应用程序是用 react + redux 制作的,并与 webpack 捆绑在一起。
store.js
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
import { persistStore, persistCombineReducers } from 'redux-persist'; //persistReducer
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
import autoMergeLevel1 from 'redux-persist/lib/stateReconciler/autoMergeLevel1';
const persistConfig = {
key : 'primary',
storage,
stateReconciler: autoMergeLevel1
};
const persistedReducer = persistCombineReducers(persistConfig, rootReducer);
const actionSanitizer = (action) => (
action.type === 'ADD_FILE' && action.libraryEntry ?
{ ...action,
libraryEntry: {
artwork: '<<LARGE_ARTWORK_BUFFER>>'
}
} : action
);
const composeEnhancers =
typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
name : 'Melo',
actionSanitizer,
stateSanitizer: (state) => state.library.files ? {
...state, library: {
files: '<<LONG_LIST_OF_FILES>>'
}
} : state
})
: compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk)
);
const configureStore = (initialState) => {
const store = createStore(persistedReducer, initialState, enhancer);
const persistor = persistStore(store);
return { store, persistor };
};
export default configureStore;
每个减速器定义为:
import * as constants from '../../constants/settings';
const ACTION_HANDLERS = {
[constants.SET_ERROR_REPORTING]: (state, { allowReporting }) => {
return {
...state,
error: {
allowReporting
}
};
},
[constants.SET_ERROR_MODAL]: (state, { allowErrorModal }) => {
return {
...state,
error: {
allowErrorModal
}
};
},
[constants.DISABLE_ERROR_REPORTING]: (state) => {
return {
...state,
error: {
allowReporting: false
}
};
}
};
export const initialState = {
error: {
allowReporting : false,
allowErrorModal: true
}
};
const settingsReducer = (state = initialState, action) => {
const handler = ACTION_HANDLERS[action.type];
return handler ? handler(state, action) : state;
};
export default settingsReducer;
rootReducer 在此处导出:
import library from './library';
import player from './player';
import view from './view';
import settings from './settings';
export default {
library,
player,
view,
settings
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BarLoader } from 'react-spinners';
import { PersistGate } from 'redux-persist/integration/react';
import configureStore from './store';
import MainView from './app';
import './styles/global.scss';
const { store, persistor } = configureStore({});
const loading = <BarLoader color={'#3E8BD3'} size={25}/>;
require('dotenv').config();
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={loading} persistor={persistor}>
<MainView/>
</PersistGate>
</Provider>,
document.getElementById('root')
);
我在 redux-persist
github 个问题 here 中做了 post 个问题。几年前有几个线程针对这个特定问题,但这些解决方案对我不起作用。感谢您提供的所有帮助!
更新:
我在第一个答案中实施了建议
编辑:我写得太快了,没有足够的思考。这个连看都不看
我可能是错的,但我认为您的商店应该在 store.js
文件中创建一次。
阅读这一行,我猜你每次重新加载或启动你的应用程序时都会创建一个新商店,这会使你丢失持久数据:
const { store, persistor } = configureStore({});
您最好在 store.js
文件中导出您的商店:
...
const store = createStore(persistedReducer, initialState, enhancer);
const persistor = persistStore(store);
export {
store,
persistor
}
然后将您的商店导入 App.js
文件:
import { store, persistor } from './store'
希望对您有所帮助
问题是我的 webpack 配置不正确,我的代码是 运行 没有正确设置的旧版本。这是使我能够正常工作的最终文件!
src/store/index.js
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
import { persistStore, persistCombineReducers } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel1 from 'redux-persist/lib/stateReconciler/autoMergeLevel1';
import logger from 'redux-logger';
const persistConfig = {
key : 'primary',
storage,
stateReconciler: autoMergeLevel1
};
const persistedReducer = persistCombineReducers(persistConfig, rootReducer);
const actionSanitizer = (action) => (
action.type === 'ADD_FILE' && action.libraryEntry ?
{ ...action,
libraryEntry: {
artwork: '<<LARGE_ARTWORK_BUFFER>>'
}
} : action
);
const composeEnhancers =
typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
name : 'Melo',
actionSanitizer,
stateSanitizer: (state) => state.library.files ? {
...state, library: {
files: '<<LONG_LIST_OF_FILES>>'
}
} : state
})
: compose;
const middlewares = [thunk, logger];
const enhancer = composeEnhancers(
applyMiddleware(...middlewares)
);
const reduxStore = createStore(persistedReducer, {}, enhancer);
const persistor = persistStore(reduxStore);
const store = { reduxStore, persistor };
export default store;
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BarLoader } from 'react-spinners';
import { PersistGate } from 'redux-persist/integration/react';
import MainView from './app';
import registerServiceWorker from './registerServiceWorker';
import './styles/global.scss';
import store from './store';
const { reduxStore, persistor } = store;
registerServiceWorker();
const loading = <BarLoader color={'#3E8BD3'} size={25}/>;
require('dotenv').config();
ReactDOM.render(
<Provider store={reduxStore}>
<PersistGate loading={loading} persistor={persistor}>
<MainView/>
</PersistGate>
</Provider>,
document.getElementById('root')
);
src/reducers/index.js
import library from './library';
import player from './player';
import view from './view';
import settings from './settings';
export default {
library,
player,
view,
settings
};
webpack.config.js
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { spawn } = require('child_process');
// Config directories
const SRC_DIR = path.resolve(__dirname, 'src');
const OUTPUT_DIR = path.resolve(__dirname, './build');
// Any directories you will be adding code/files into, need to be
// added to this array so webpack will pick them up
const defaultInclude = [SRC_DIR];
module.exports = {
entry : `${SRC_DIR}/index.js`,
mode : 'development',
output: {
path : OUTPUT_DIR,
publicPath: path.join('./'),
filename : 'bundle.js'
},
module: {
rules: [
{
test: /\.(s*)css$/,
use : [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test : /\.js$/,
exclude: /node_modules(?!(\/|\)js-utils)/,
loader : 'babel-loader'
},
{
test : /\.jsx$/,
exclude: /node_modules(?!(\/|\)js-utils)/,
loader : 'babel-loader'
},
{
test : /\.(jpe?g|png|gif)$/,
use : [{ loader: 'file-loader?name=img/[name]__[hash:base64:5].[ext]' }],
include: defaultInclude
},
{
test : /\.(eot|svg|ttf|woff|woff2)$/,
use : [{ loader: 'file-loader?name=font/[name]__[hash:base64:5].[ext]' }],
include: defaultInclude
}
]
},
target : 'electron-renderer',
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject : 'body'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
],
devtool : 'cheap-source-map',
devServer: {
contentBase: OUTPUT_DIR,
stats : {
colors : true,
chunks : false,
children: false
},
before() {
spawn(
'electron',
['./public/electron.js'],
{ shell: true, env: process.env, stdio: 'inherit' }
)
.on('close', code => process.exit(0))
.on('error', spawnError => console.error(spawnError));
}
}
};
感谢所有帮助过我的人!