Hello,
We have an app that uses connected-react-router, and I tried the minimal integration with init (from here).
Initial code
import { AppContainer } from 'react-hot-loader'
import { applyMiddleware, compose, createStore } from 'redux'
import { createBrowserHistory } from 'history'
import { routerMiddleware, connectRouter } from 'connected-react-router'
import {Provider } from 'react-redux'
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import thunk from 'redux-thunk'
import alerts from './modules/alerts'
import userInfo from './modules/userInfo'
const history = createBrowserHistory();
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const middlewares = [routerMiddleware(history), thunk];
const rootReducer = combineReducers({
alerts: AlertsReducer,
userInfo: UserInfoReducer
});
const store = createStore(
connectRouter(history)(rootReducer),
composeEnhancer(
applyMiddleware(...middlewares)
),
);
const render = () => {
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<App history={history}/>
</Provider>
</AppContainer>,
document.getElementById('react-root')
)
};
rematch integration
import { AppContainer } from 'react-hot-loader'
import { applyMiddleware, compose, createStore } from 'redux'
import { createBrowserHistory } from 'history'
import { routerMiddleware, connectRouter } from 'connected-react-router'
import {Provider } from 'react-redux'
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import rootReducer from './modules'
import thunk from 'redux-thunk'
import alerts from './modules/alerts'
import userInfo from './modules/userInfo'
const history = createBrowserHistory();
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const middlewares = [routerMiddleware(history), thunk];
import { init } from "@rematch/core";
const store = init({
redux: {
reducers: {
alerts,
userInfo,
},
middlewares: [...middlewared]
},
});
// const store = createStore(
// connectRouter(history)(rootReducer),
// composeEnhancer(
// applyMiddleware(...middlewares)
// ),
// );
const render = () => {
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<App history={history}/>
</Provider>
</AppContainer>,
document.getElementById('react-root')
)
};
We get some errors from the components themselves (regarding missing location from connected-react-router), but I think the main issue is this one
ConnectedRouter.js:58 Uncaught (in promise) TypeError: Cannot read property 'pathname' of undefined
at ConnectedRouter.js:58
at Object.p [as dispatch] (rematch.prod.min.js:34)
at dispatch (<anonymous>:1:38399)
at index.js:14
at middleware.js:25
at rematch.prod.min.js:122
at rematch.prod.min.js:116
at Object.next (rematch.prod.min.js:117)
at rematch.prod.min.js:99
at new Promise (<anonymous>)
After some digging the the connected-react-router code, I realized that the problem is connectRouter. This rewrites the global reducer function to a new one, but rematch needs an object with a function for each reducer.
I managed to make a individual router reducer like so, and the application works again 馃槃:
const merge = (state, payload) => ({ ...state, ...payload });
const routerReducer = (history) => {
const initialState = {
location: history.location,
action: history.action,
};
return (state = initialState, { type, payload } = {}) => {
if (type === LOCATION_CHANGE) {
return merge(state, payload)
}
return state
}
};
import { init } from "@rematch/core";
const store = init({
redux: {
reducers: {
alerts,
userInfo,
router: routerReducer(history)
},
middlewares: [...middlewares]
},
});
Can a function be used in [redux][reducers] instead of an object? Is it maybe another keyword?
You really hacked this one out. Your final working solution looks quite clean. Nice work.
Good question. At this point reducers is only an object of key/functions.
There is a concept of rootReducers that you might have found interesting.
Thanks, I'll look into that in case I'll need another library that integrates in a similar way.
Awesome project, by the way, it reduces all that usual boilerplate :smiley:
How and from where to invoke LOCATION_CHANGE action?
Most helpful comment
After some digging the the
connected-react-routercode, I realized that the problem isconnectRouter. This rewrites the global reducer function to a new one, but rematch needs an object with a function for each reducer.I managed to make a individual router reducer like so, and the application works again 馃槃:
Can a function be used in
[redux][reducers]instead of an object? Is it maybe another keyword?