使用connected-react-router版本6.4.0和历史记录4.10.0。 使用react-redux版本6。 使用redux-injectors,redux-saga和redux-logger。
出现错误,表明它无法在减速器树中找到路由器。 我不知道怎么了。
这是我的index.js文件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './containers/App';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router/immutable';
import configureStore from './configureStore';
import history from './utils/history';
import initializeIconLibrary from './utils/initializeIconLibrary';
const MOUNT_NODE = document.getElementById('root');
const store = configureStore({}, history);
initializeIconLibrary();
const render = () => {
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<React.StrictMode>
<App />
</React.StrictMode>
</ConnectedRouter>
</Provider>,
MOUNT_NODE
);
}
if (module.hot) {
// Hot reloadable React components and translation json files
// modules.hot.accept does not accept dynamic dependencies,
// have to be constants at compile-time
module.hot.accept('./containers/App', () => {
ReactDOM.unmountComponentAtNode(MOUNT_NODE);
render();
});
}
render();
// Install ServiceWorker and AppCache in the end since
// it's not most important operation and if main code fails,
// we do not want it installed
if (process.env.NODE_ENV === 'production') {
require('offline-plugin/runtime').install(); // eslint-disable-line global-require
}
configureStore.js
/**
* Create the store with dynamic reducers
*/
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import { fromJS, Iterable } from 'immutable';
import { routerMiddleware, connectRouter } from 'connected-react-router/immutable';
/*
** Export the store enhancer
** createInjectorsEnhancer -> takes options with two main properties
** createReducer which will return a root reducer, and pass injected reducers as key value pair.
** runSaga which should be the sagaMiddleware.run method.
*/
import { createInjectorsEnhancer, forceReducerReload } from 'redux-injectors';
import { createLogger } from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
import createReducer from './reducers';
const sagaMiddleware = createSagaMiddleware();
const stateTransformer = state => {
if(Iterable.isIterable(state)) return state.toJS();
return state;
}
export default function configureStore(initialState = {}, history) {
const middlewares = [sagaMiddleware, routerMiddleware(history), createLogger(stateTransformer, {})];
const { run: runSaga } = sagaMiddleware;
const composeEnhancers =
process.env.NODE_ENV !== 'production' &&
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose;
const enhancers = [
applyMiddleware(...middlewares),
createInjectorsEnhancer({
createReducer,
runSaga
})
];
const store = createStore(
applyMiddleware(...middlewares),
composeEnhancers(...enhancers)
)
store.runSaga = sagaMiddleware.run;
store.injectReducers = {};
store.injectSaga = {};
// Make reducers hot reloadable, see http://mxs.is/googmo
/* istanbul ignore next */
if (module.hot) {
module.hot.accept('./reducers', () => {
// store.replaceReducer(createReducer(store.injectReducers));
forceReducerReload(store);
});
}
return store;
}
Create Reducer函数负责创建根reducer。
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router/immutable';
import { reducer as formReducer } from 'redux-form/immutable';
import history from './utils/history';
/**
* Merges the main reducer with the router state and dynamically injected reducers
*/
export default function createReducer(injectedReducers = {}) {
const rootReducer = combineReducers({
...injectedReducers,
router: connectRouter(history),
form: formReducer.plugin({}),
});
return rootReducer;
}
package.json
{
"name": "rantsnow",
"version": "0.1.0",
"private": true,
"main": "server/index.js",
"proxy*": "http://localhost:10000",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.31",
"@fortawesome/free-brands-svg-icons": "^5.15.0",
"@fortawesome/free-regular-svg-icons": "^5.15.0",
"@fortawesome/free-solid-svg-icons": "^5.15.0",
"@fortawesome/react-fontawesome": "^0.1.11",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"axios": "^0.20.0",
"bcrypt": "^5.0.0",
"bluebird": "^3.7.2",
"body-parser": "^1.19.0",
"bootstrap": "^4.5.2",
"bootstrap-icons": "^1.0.0",
"connected-react-router": "6.4.0",
"date-fns": "^2.16.1",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-session": "^1.17.1",
"history": "4.9.0",
"immutable": "3.8.2",
"lodash": "^4.17.20",
"mysql2": "^2.2.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-icons": "^3.11.0",
"react-popper": "^2.2.3",
"react-redux": "^7.2.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.3",
"react-toastify": "^6.0.8",
"react-toastify-redux": "^1.0.0-rc.2",
"react-transition-group": "^4.4.1",
"reactstrap": "^8.6.0",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.8",
"redux-form": "^8.3.6",
"redux-injectors": "^1.3.0",
"redux-logger": "3.0.6",
"redux-saga": "^1.1.3",
"redux-storage": "^4.1.2",
"redux-storage-engine-localstorage": "^1.1.4",
"reflect-metadata": "^0.1.13",
"reselect": "^4.0.0",
"universal-cookie": "^4.0.3"
},
"scripts": {
"start": "set PORT=3000 && react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"prettier": "2.1.2"
}
}