React-redux-router 迁移到 connect-react-router

Posted

技术标签:

【中文标题】React-redux-router 迁移到 connect-react-router【英文标题】:React-redux-router migrate to connect-react-router 【发布时间】:2020-07-05 15:10:41 【问题描述】:

我从https://github.com/briancappello/flask-react-spa 构建项目 并尝试升级依赖项。

然后我得到了这个错误。 我按照 connect-react-router 指南设置,然后发生了这个错误。 创建减速器时发生此错误, 当初始 reducer 方法将 undefind ibj 传递给 reducer 方法 那么历史的 createHref 需要从此 obj 获取路径名 并且发生了这个错误...

谁能给点建议?也许是依赖问题?

错误堆栈

未捕获的类型错误:无法读取未定义的属性“路径名” 在 createPath (history.js:70) 在 createHref (history.js:366) 在 eval (redux.js:361) 在 Array.forEach () 在 assertReducerShape (redux.js:359) 在 combineReducers (redux.js:422) 在 createReducer (reducers.js?9c0a:11) 在 configureStore (configureStore.js?2ddb:35) 在 Module.eval (index.js?7df2:24) 在 eval (index.js:109)

reducer.js

import  combineReducers  from 'redux'
import  connectRouter  from 'connected-react-router'
import formReducer from 'redux-form/es/reducer'

import  loadingBarReducer  from 'react-redux-loading-bar'

import securityReducer from 'security/reducer'
import flashReducer from 'site/reducers/flash'


const createReducer = (injectedReducers) => combineReducers(
    router: connectRouter(injectedReducers),
    security: securityReducer,
    flash: flashReducer,
    form: formReducer,
    loadingBar: loadingBarReducer,

    ...injectedReducers,
)
export default createReducer

configureStore.js

import  applyMiddleware, compose, createStore  from 'redux'
import  routerMiddleware  from 'connected-react-router'
import  connectRouter  from 'connected-react-router'
import  loadingBarMiddleware  from 'react-redux-loading-bar'
import createSagaMiddleware from 'redux-saga'
import createReducer from 'reducers'
import getSagas from 'sagas'
import  flashClearMiddleware  from 'site/middleware/flash'

const isDev = process.env.NODE_ENV !== 'production'
const hasWindowObject = typeof window === 'object'

const sagaMiddleware = createSagaMiddleware()

export default function configureStore(initialState, history) 
  const middlewares = [
    sagaMiddleware,
    routerMiddleware(history),
    loadingBarMiddleware( promiseTypeSuffixes: ['REQUEST', 'FULFILL'] ),
    flashClearMiddleware,
  ]

  const enhancers = [
    applyMiddleware(...middlewares),
  ]

  const composeEnhancers =
    isDev && hasWindowObject && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
      ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
      : compose
  const store = createStore(
    createReducer(history),
    initialState,
    composeEnhancers(...enhancers)
  )

  // extensions
  store.runSaga = sagaMiddleware.run
  store.injectedReducers = 
  store.injectedSagas = 

  let runningSagas = sagaMiddleware.run(function *() 
    yield getSagas()
  )

  if (module.hot) 
    module.hot.accept('./reducers', () => 
      const nextCreateReducer = require('./reducers').default
      store.replaceReducer(connectRouter(history)(nextCreateReducer(store.injectedReducers)))
    )

    module.hot.accept('./sagas', () => 
      const nextGetSagas = require('./sagas').default
      runningSagas.cancel()
      runningSagas.done.then(() => 
        runningSagas = sagaMiddleware.run(function *() 
          yield nextGetSagas()
        )
      )
    )
  

  return store

这是我的依赖项

"dependencies": 
    "@babel/polyfill": "7.4.3",
    "@hot-loader/react-dom": "^16.8.6",
    "acorn": "^6.4.1",
    "babel-polyfill": "^6.26.0",
    "chalk": "2.4.2",
    "classnames": "^2.2.6",
    "compression": "1.7.4",
    "connected-react-router": "^6.8.0",
    "core-js": "^3.6.4",
    "date-fns": "^2.11.0",
    "fontfaceobserver": "2.1.0",
    "history": "4.9.0",
    "hoist-non-react-statics": "3.3.0",
    "immer": "3.0.0",
    "immutable": "^3.8.2",
    "intl": "1.2.5",
    "invariant": "2.2.4",
    "ip": "1.1.5",
    "isomorphic-fetch": "^2.2.1",
    "js-cookie": "^2.2.1",
    "lodash": "^4.17.15",
    "minimist": "^1.2.5",
    "normalize.css": "^8.0.1",
    "path-to-regexp": "^6.1.0",
    "prop-types": "15.7.2",
    "query-string": "^6.11.1",
    "react": "16.8.6",
    "react-bulma-components": "^3.2.0",
    "react-dom": "16.8.6",
    "react-helmet": "6.0.0-beta",
    "react-highlight": "^0.12.0",
    "react-intl": "2.8.0",
    "react-loadable": "^5.5.0",
    "react-redux": "^7.2.0",
    "react-redux-loading-bar": "^4.6.0",
    "react-router-dom": "5.0.0",
    "react-svg": "^11.0.14",
    "redux": "4.0.1",
    "redux-form": "^8.2.3",
    "redux-saga": "1.0.2",
    "reselect": "4.0.0",
    "sanitize.css": "8.0.0",
    "seamless-immutable": "^7.1.4",
    "styled-components": "4.2.0",
    "utf-8-validate": "^5.0.2",
    "warning": "^4.0.3"
  ,
  "devDependencies": 
    "@types/react": "^16.9.23",
    "add-asset-html-webpack-plugin": "3.1.3",
    "canvas": "^2.6.1",
    "circular-dependency-plugin": "5.0.2",
    "compare-versions": "3.4.0",
    "compression-webpack-plugin": "2.0.0",
    "coveralls": "3.0.3",
    "css-loader": "2.1.1",
    "eslint": "5.16.0",
    "eslint-config-airbnb": "17.1.0",
    "eslint-config-airbnb-base": "13.1.0",
    "eslint-config-prettier": "4.1.0",
    "eslint-import-resolver-webpack": "0.11.1",
    "eslint-plugin-import": "2.17.2",
    "eslint-plugin-jsx-a11y": "6.2.1",
    "eslint-plugin-prettier": "3.0.1",
    "eslint-plugin-react": "7.12.4",
    "eslint-plugin-react-hooks": "1.6.0",
    "eslint-plugin-redux-saga": "1.0.0",
    "express": "^4.17.1",
    "express-http-proxy": "^1.6.0",
    "fibers": "^4.0.2",
    "file-loader": "3.0.1",
    "html-loader": "0.5.5",
    "html-webpack-plugin": "3.2.0",
    "image-webpack-loader": "4.6.0",
    "imports-loader": "0.8.0",
    "jest-cli": "24.7.1",
    "jest-dom": "3.1.3",
    "jest-styled-components": "^6.3.4",
    "jsdom": "^16.2.1",
    "json-loader": "^0.5.7",
    "lint-staged": "8.1.5",
    "ngrok": "3.1.1",
    "node-plop": "0.18.0",
    "node-sass": "^4.13.1",
    "null-loader": "0.1.1",
    "offline-plugin": "5.0.6",
    "plop": "2.3.0",
    "pre-commit": "1.2.2",
    "prettier": "1.17.0",
    "react-app-polyfill": "0.2.2",
    "react-hot-loader": "^4.12.20",
    "react-test-renderer": "16.8.6",
    "react-testing-library": "6.1.2",
    "redbox-react": "^1.6.0",
    "resolve-url-loader": "^3.1.1",
    "rimraf": "2.6.3",
    "sass": "^1.26.3",
    "sass-loader": "^8.0.2",
    "shelljs": "0.8.3",
    "style-loader": "0.23.1",
    "stylelint": "10.0.1",
    "stylelint-config-recommended": "2.2.0",
    "stylelint-config-styled-components": "0.1.1",
    "stylelint-processor-styled-components": "1.6.0",
    "svg-url-loader": "2.3.2",
    "terser-webpack-plugin": "1.2.3",
    "url-loader": "1.1.2",
    "webpack": "^4.42.1",
    "webpack-bundle-analyzer": "^3.6.1",
    "webpack-cli": "3.3.0",
    "webpack-dev-middleware": "3.6.2",
    "webpack-hot-middleware": "2.24.3",
    "webpack-pwa-manifest": "^4.2.0",
    "whatwg-fetch": "3.0.0"
  

index.js

import 'babel-polyfill'

// this must come before everything else otherwise style cascading doesn't work as expected
import 'main.scss'

import  AppContainer as HotReloadContainer  from 'react-hot-loader'
import  areComponentsEqual  from 'react-hot-loader';
import React from 'react'
import ReactDOM from 'react-dom'
import createBrowserHistory from 'history'

import configureStore from 'configureStore'
import App from 'components/App'
import  login  from 'security/actions'
import  flashInfo  from 'site/actions'
import SecurityApi from 'security/api'
import  storage  from 'utils'


const APP_MOUNT_POINT = document.getElementById('app')

const initialState = 
const history = createBrowserHistory()
const store = configureStore(initialState, history)

const renderRootComponent = (Component) => 
  ReactDOM.render(
    <HotReloadContainer>
      <Component store=store history=history />
    </HotReloadContainer>,
    APP_MOUNT_POINT
  )


const token = storage.getToken()
store.dispatch(login.request())
SecurityApi.checkAuthToken(token)
  .then(( user ) => 
    store.dispatch(login.success( token, user ))
  )
  .catch(() => 
    store.dispatch(login.failure())
  )
  .then(() => 
    store.dispatch(login.fulfill())
    renderRootComponent(App)
    const isAuthenticated = store.getState().security.isAuthenticated
    const alreadyHasFlash = store.getState().flash.visible
    if (isAuthenticated && !alreadyHasFlash) 
      store.dispatch(flashInfo('Welcome back!'))
    
  )

if (module.hot) 
  module.hot.accept('./components/App.js', () => 
    ReactDOM.unmountComponentAtNode(APP_MOUNT_POINT)
    const NextApp = App.default
      areComponentsEqual(NextApp)
    renderRootComponent(NextApp)
  )

App.js

import React from 'react'
import  Provider  from 'react-redux'
import  ConnectedRouter  from 'connected-react-router'
import Helmet from 'react-helmet'
import   history  from './index'
import  NavBar, ProgressBar  from 'components'
import  SITE_NAME, COPYRIGHT  from 'config'
import Routes from 'routes'

const AppLayout = () => (
  <div className="fixed-nav-top">
    <Helmet titleTemplate=`%s - $SITE_NAME`
            defaultTitle=SITE_NAME
    />
    <ProgressBar />
    <header>
      <NavBar />
    </header>
    <main>
      <Routes />
    </main>
    <footer className="center">
       Copyright new Date().getFullYear() COPYRIGHT
    </footer>
  </div>
)
export default (props) => (
  <Provider store=props.store>
    <ConnectedRouter history=history>
      <AppLayout />
    </ConnectedRouter>
  </Provider>
)

【问题讨论】:

【参考方案1】:

请检查路径

import   history  from './index'

【讨论】:

是的,我将其更改为 App.js 中的 props.history 但问题仍然存在

以上是关于React-redux-router 迁移到 connect-react-router的主要内容,如果未能解决你的问题,请参考以下文章

获取`元素类型无效:使用react-redux-router时预期出现字符串`错误

gitlab 搭建 备份 升级 迁移恢复

从生成器迁移到异步/等待

从 Scala 迁移到 Go,永不回头

Elasticsearch集群数据迁移

web工程迁移---weblogic8迁移到jboss5遇到的异常