React Router Redux返回导致无限循环

时间:2017-10-12 16:35:01

标签: javascript reactjs react-router react-redux react-router-redux

我有一个使用React + Redux构建的应用程序。我使用React Router和React Router Redux进行路由。我注意到很奇怪的行为。单击后退按钮一次,从0到-1就可以了。但是当你第二次点击它,打算从-1到-2时,你会回到0.后续点击循环在0和-1之间。这种行为与推送到最后一个位置的历史记录一致,而不是一致。这是这些库的预期行为吗?如果不是我错误地使用它们?

以下是我认为相关的代码段。文件不完整(太大)但我认为这是必不可少的,愿意在需要时分享更多。

root.tsx

import { Router, browserHistory } from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'

const history = syncHistoryWithStore(browserHistory, store)

const renderAsyncConnect = props =>
  <ReduxAsyncConnect
    {...props}
    helpers={{ client }}
    filter={notDeferredItems}
  />

const Root = () =>
  <Provider store={store} key="provider">
    <Router render={renderAsyncConnect} history={history}>
      {routes}
    </Router>
  </Provider>

export default Root

我还有一个中间件监听推送操作。我知道我被建议使用history.listen,但是这个中间件在竞争条件方面非常强大,并且只是在我们转换系统时暂时兼容。

以下是路由中间件之后的中间件的净效果:

const browseStateMiddleware = ({ dispatch, getState }) => next => action => {
  if (action.type === '@@router/LOCATION_CHANGE') {
    // some dispatching of actions deleted here for clarity
    return next(action)
  }
}

create-store.js

import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension/logOnly'
import { createStore as _createStore, applyMiddleware } from 'redux'
import { routerMiddleware } from 'react-router-redux'

import clientMiddleware from './middleware/client-middleware'
import browseStateMiddleware from './middleware/browse-state-middleware'

import combinedReducers from './modules/reducer'
import types from './modules/account/types'

export default function createStore(history, client, data, persister) {
  const storeData = data

  // Sync dispatched route actions to the history
  const reduxRouterMiddleware = routerMiddleware(history)

  const middleware = [
    browseStateMiddleware,
    reduxRouterMiddleware,
    clientMiddleware(client),
    analyticsMiddleware,
    thunk,
  ]

  const composeEnhancers = composeWithDevTools(
    {
      // options like actionSanitizer, stateSanitizer
    }
  )

  // See https://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store/35641992#35641992
  const rootReducer = (state, action) => {
    if (action.type === types.LOGOUT) {
      if (persister) {
        persister.clear()
      }
      return combinedReducers(undefined, action)
    }

    return combinedReducers(state, action)
  }

  const store = _createStore(
    rootReducer,
    storeData,
    composeEnhancers(
      applyMiddleware(...middleware)
      // other store enhancers
    )
  )

  window.store = store

  if (__DEVELOPMENT__ && module.hot) {
    module.hot.accept('./modules/reducer', () => {
      store.replaceReducer(System.import('./modules/reducer'))
    })
  }

  return store
}

这里有什么问题吗?

1 个答案:

答案 0 :(得分:2)

此问题很可能是由以下原因引起的:

const browseStateMiddleware = ({ dispatch, getState }) => next => action => {
  if (action.type === '@@router/LOCATION_CHANGE') {
    // some dispatching of actions deleted here for clarity
    return next(action)
  }
}

您分发的动作是在商店中更新路由之前发生的,这导致此行为源自react-router-redux(我已经看到它是在4.0.8版本中复制的)。

一种解决方法是执行以下操作:

const browseStateMiddleware = ({ dispatch, getState }) => next => action => {
  if (action.type === '@@router/LOCATION_CHANGE') {
    next(action);
    // dispatch your actions here
    return;
  }
}

这样可以保证您在正确的时间正确更新商店。