Dva: API 文档 extraEnhancers 举例的 redux-persist 目前 5.10.0 版本不兼容

Created on 29 Jun 2018  ·  9Comments  ·  Source: dvajs/dva

原文:

Specify extra StoreEnhancers.

e.g. use dva with redux-persist:

import { persistStore, autoRehydrate } from 'redux-persist';
const app = dva({
  extraEnhancers: [autoRehydrate()],
});
persistStore(app._store);

===============================

目前 redux-persist 5.10.0 版本已经没有export autoRehydrate ,但是我通过 npm 并没有检查到它和 dva.js 不兼容。
而且我的 app 在初始化之后 _store 是空的,也不能成功执行 persistStore。
请问是我哪里用的不对吗?十分疑惑

documentation wontfix

Most helpful comment

我是这样写的:

const persistEnhancer = () => createStore => (reducer, initialState, enhancer) => createStore(persistReducer(persistConfig, reducer), initialState, enhancer);

const app = dva({
  history: getHistory({
    basename: config.basename,
  }),
  extraEnhancers: [persistEnhancer()],
  onError(error) {
    // eslint-disable-next-line no-console
    processError(error);
  },
});

目前来说没问题,很完美,但是我不知道如何解决hot replacement的问题~

All 9 comments

import { persistStore, persistReducer } from 'redux-persist'

······
const app = dva({
  ······
  onReducer: (combineReducer) => {
    return persistReducer(
      {
        key: 'redux-storage',
        whitelist: ['BASE'],
        keyPrefix: 'everlast-',
        debug: process.env.NODE_ENV === 'development',
        storage: storageProvider
      },
      combineReducer
    )
  }
})

······
app.start('#main')
persistStore(app._store)

=======

现在这样写好像可以正常用了。
useing these code , it looks works fine :)

还是有点问题,我用 redux-persist 持久化了 token,但是上面那种写法 token 会在 componentDidMount 之后恢复到 store 里。我在第一次渲染页面的时候无法获取原先保存的token,persist 因为支持 asyncStorage 所以它恢复 store 是异步的。目前我恢复 store 需要 50ms ,而 react 初始渲染完成只要 40ms,执行页面请求的时候,token 还没有恢复过来。

······
app.router(() => {
  loaderState().set('app', app)
  persistStore(app._store)
  return (
    <Router>
      <Route path={'/'} component={routeList['/main-rect']} />
    </Router>
  )
})


reduxModels().map((model) => app.model(model))

app.start('#main')

······
render() {
    const { comLoading, rehydrated } = this.props
    console.log('rehydrated', rehydrated);
    return (
      <object className={'base'} type={'base'}>
        <div className={'common'}>
          {this.comloadingDOM(comLoading)}
        </div>
        {
          rehydrated ? (
            <Switch>
              {
                Object.keys(routeList).map((route) => {
                  return (<Route path={route} component={routeList[route]} key={route} />)
                })
              }
              <Route path={'(/)'} component={routeList['/home']} />
              <Route path={'*'} component={routeList['/not-found']} />
            </Switch>
          ) : null
        }
      </object>
    )
  }
······
export default combineComponent({
  c: baseComponent,
  model: model,
  modelEx: [
    {
      namespace: '_persist',
      stateProp: 'rehydrated'
    }
  ]
})

目前有了一个临时解决办法,mapStateToProps 绑定了store里 _persist.rehydrated 这个props,判断props rehydrated=true 恢复成功之后再渲染路由。

我是这样写的:

const persistEnhancer = () => createStore => (reducer, initialState, enhancer) => createStore(persistReducer(persistConfig, reducer), initialState, enhancer);

const app = dva({
  history: getHistory({
    basename: config.basename,
  }),
  extraEnhancers: [persistEnhancer()],
  onError(error) {
    // eslint-disable-next-line no-console
    processError(error);
  },
});

目前来说没问题,很完美,但是我不知道如何解决hot replacement的问题~

sorrycc 大佬写的有个 dva-hmr ,可惜跟我现在的玩法不兼容,
我也没解决掉这个 hot replacement 的问题。。。

@sg-zzk 你上文提到的问题,redux-persist提供了PersistGate组件,其原理貌似和你做的事是一样的~

@sg-zzk PS:使用PersistGate的方法在 #1419

HMR临时解决方案,防止model结构变更时,redux-persist rehydrate异常,如果存放在localSorage,也可以避免发版异常

环境:umi、dva、immer、redux-persist
model里面增加clear reducer

demo代码

// model.js
const initState={
  list: [],
  current: {},
  query: {},
  total: 0
}

export default {
    namespace:'test',
    state:initState,
    reducers:{
       clear() {
         return initState
       }
   }
}

//调用时机可根据自己的业务需要,比如subscriptions路由,componentDidUnmount,logout等

另外redux-persist,选择状态树合并方案为autoMergeLevel2

import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2'

onReducer: reducer => {
  return persistReducer(
    {
      key: 'redux',
      storage: storage,
      stateReconciler:autoMergeLevel2
    },
    reducer
  )
}

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings