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的主要内容,如果未能解决你的问题,请参考以下文章