简体   繁体   English

React Router Redux返回导致无限循环

[英]React Router Redux going back causing an infinite loop

I have an app built with React + Redux. 我有一个使用React + Redux构建的应用程序。 I am using React Router with React Router Redux for routing. 我使用React Router和React Router Redux进行路由。 I have noticed very odd behavior. 我注意到很奇怪的行为。 When you click the back button once, from 0 to -1 it works. 单击后退按钮一次,从0到-1就可以了。 But when you click it a second time, intending to go from -1 to -2, you instead go back to 0. Subsequent clicks loop between 0, and -1. 但是当你第二次点击它,打算从-1到-2时,你会回到0.后续点击循环在0和-1之间。 This behavior is consistent with, rather than popping from history pushing to the last location. 这种行为与推送到最后一个位置的历史记录一致,而不是一致。 Is this the expected behavior of these libraries? 这是这些库的预期行为吗? If not am I using them incorrectly? 如果不是我错误地使用它们?

Here are what I believe to be the relevant pieces of code. 以下是我认为相关的代码片段。 The files are not complete (much too big) but this is what I think is essential, willing to share more if needed. 文件不完整(太大)但这是我认为必不可少的,愿意在需要时分享更多。

root.tsx : 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

I also have a middleware listening for push actions. 我还有一个中间件监听推送操作。 I know I am advised to use history.listen , but this middleware is robust against race conditions, and is only there for compatibility for the time being as we transition our system. 我知道我被建议使用history.listen ,但是这个中间件对竞争条件非常强大,并且只是在我们转换系统时暂时兼容。

Here is the net effect of the middleware that is after the routing middleware: 以下是路由中间件之后的中间件的净效果:

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 : 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
}

Is anything wrong here? 这里有什么不对吗?

This issue is most likely caused by this: 这个问题很可能是由此造成的:

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

The actions you dispatch take place before the routing is updated in the store which causes this behavior originating from react-router-redux (I have seen it reproduced with version 4.0.8). 您发送的操作发生在商店中更新路由之前,这会导致此行为源自react-router-redux (我已经看到它使用版本4.0.8重现)。

One way to handle it could be to do the following: 处理它的一种方法可能是执行以下操作:

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

This way you are guaranteed to have the store updated correctly at the right time. 这样,您可以确保在正确的时间正确更新商店。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM