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));
    }
  }
};

感谢所有帮助过我的人!