Getting 'Uncaught TypeError: Cannot read property 'type' of undefined' when using with react-router 2.x #182
Comments
I am receiving this too. Must be related to the updated API of react router |
@trattles is this on load? Are you dispatching any actions in your app using the history API or routingActions? This looks like you are dispatching an action that has no type field defined which is not a valid redux action. If you add the loggerMiddleware do you see a console log for an action with no type field? |
@mjrussell this error occurs on load. I am not dispatching any actions via the history API. Thus far all I've done is attempt to hook up redux-simple-router, but never got far enough to attempt to dispatch actions to it because I get this error on the initial render. Before attempting to implement redux-simple-router, react-router was running just fine and the application rendered with no errors. I'll add the logger middleware and see if it gives me anything useful. |
Looks like the error is related to this line
It must have to do with me setting the initialState incorrectly. The initialState passed from my server does not include the routing state. If I do not pass an initialState to my reducer it seems to run correctly. Do I need to manually set a specific initial state when utilizing redux-simple-router if I want to pass other state parameters? |
@trattles damn I thought that might be it when I saw you initalState. Can you try setting your initial state of the routeReducer to this: https://github.com/rackt/redux-simple-router/blob/master/src/index.js#L32 |
@mjrussell I tried setting it that way, but I've got other initial state items. So my initial state looks like this. const initialState = {
profile: {
name: 'Bob',
age: 10
},
location: undefined,
messages: [],
request:{
userAgent: req.headers['user-agent']
},
} When I start with this, I get the same error. My guess is the issue is here function routeReducer() {
var state = arguments.length <= 0 || arguments[0] === undefined ? initialState : arguments[0];
var _ref = arguments[1];
var type = _ref.type;
var location = _ref.location;
if (type !== UPDATE_LOCATION) {
return state;
}
return { location: location };
} var _ref = arguments[1]. Arguments[1] is undefined. Maybe I'm off though, but the line var type= _ref.type is what's throwing the error. |
@trattles the initalState would be: const initialState = {
profile: {
name: 'Bob',
age: 10
},
routing: {
location: undefined,
},
messages: [],
request:{
userAgent: req.headers['user-agent']
},
} But regardless I see your problem now... Change this line const store = createStoreWithMiddleware(reducer(initialState)); to const store = createStoreWithMiddleware(reducer, initialState); I bet you don't even need the initial state for the routing now though |
The second argument to the reducer should be an action. I don't know why that would not be defined. Can you break on that line and look at the stack trace, and see why it isn't being called with an action? |
I've gotten the issue resolved. The cause was how I was combining my reducers. Originally when importing my reducers I was importing already combined reducers, then running that through combine reducers again to add redux-simple-router. I refactored my reducers to instead return an object containing all my reducers, and then combine only once with redux-simple-router and everything seems to be working correctly. I also do not need to manually add routing to state. The final working entry.js looks like this const reducer = combineReducers(Object.assign({}, reducers, {routing: routeReducer }));
let initialState = window.__INITIAL_STATE__;
const simpleRouter = syncHistory(browserHistory);
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware, simpleRouter, logger)(createStore);
const store = createStoreWithMiddleware(reducer, initialState);
simpleRouter.syncHistoryToStore(store); And my reducers no longer return combined reducers, but rather return an object like this (this is imported as 'reducers' above) export default {messages, profile}; Having discovered this, I think it might be better for me to actually import redux simple router where I'm building my reducers, rather than in my entry.js, as that would eliminate my need to re-write all this on the server side. |
@trattles I have my reducers combining correctly, but still get this error. Did you make any other changes that could have effected things? |
@mjrussell my mistake - my error is actually:
My store config is a bit verbose, as I have a workaround to prevent redux-localstorage from being used server side: // Init
// ====
let rootReducer
let storage
let createStoreWithMiddleware
export const reduxRouterMiddleware = syncHistory(browserHistory)
const middleware = [
thunk,
authenticationRouter,
reduxRouterMiddleware
]
// Build createStoreWithMiddleware
// ===============================
if (typeof window !== 'undefined') {
// Client store config (include localStorage)
rootReducer = getPersistedState(anchorApp)
storage = configClientStorage()
createStoreWithMiddleware = compose(
applyMiddleware(...middleware),
persistState(storage, 'UID-1337'),
devTools(),
)(createStore)
} else {
// Server store config
rootReducer = anchorApp
createStoreWithMiddleware = compose(
applyMiddleware(...middleware),
devTools(),
)(createStore)
}
// Export store creator
// ====================
export default function configureStore(initialState) {
const store = createStoreWithMiddleware(rootReducer, initialState)
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers', () => {
const nextReducer = require('../reducers')
store.replaceReducer(nextReducer)
})
}
return store
}
client: // Init Store
// ==========
const initialState = window.__INITIAL_STATE__
const store = configureStore(initialState)
// Init Router
// ===========
reduxRouterMiddleware.listenForReplays(store)
render(
<div>
<Provider store={ store }>
<Router history={ browserHistory }>
{ routes }
</Router>
</Provider>
<DebugPanel top right bottom>
<DevTools store={ store } monitor={ LogMonitor } />
</DebugPanel>
</div>,
document.getElementById('root')
) hopefully this helps, sorry its a bit long! |
@hoodsy can you show your import statement for the browserHistory in the init section? |
@mjrussell here it is: import { compose, createStore, applyMiddleware } from 'redux'
import { devTools } from 'redux-devtools'
import thunk from 'redux-thunk'
import { syncHistory } from 'redux-simple-router'
import { browserHistory } from 'react-router' |
Hmm your case really does look like the history object passed to |
So it seems I'm on |
Hmm I dont think any of your issues are actually |
Will do, thanks for the help. |
Same issue here -- |
@hoodsy Were you able to find a fix for this issue? Looked through the stack overflow conversation, didn't see one. Thanks. |
I was able to figure it out by looking at the example: https://github.com/rackt/redux-simple-router/blob/6a9f0d22a79f48b106c2ae2beb9979a0a3ccd50b/examples/basic/app.js |
For anyone looking at this in the future, remix-run/react-router#2090 is the relevant issue for |
The problem is due to a change on the router's API: https://github.com/rackt/react-router/blob/1.0.x/docs/guides/basics/Histories.md Use this instead |
See: https://github.com/rackt/react-router/blob/master/upgrade-guides/v2.0.0.md#using-custom-histories // v1.x
import createHashHistory from 'history/lib/createHashHistory'
const history = createHashHistory({ queryKey: false })
<Router history={history}/>
// v2.0.0
import { Router, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
// useRouterHistory creates a composable higher-order function
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false })
<Router history={appHistory}/> I'm using this in server-side: import {Router, RouterContext, match, useRouterHistory} from 'react-router';
import {createMemoryHistory} from 'history';
// ...
const appHistory = useRouterHistory(createMemoryHistory)({});
const component = (
<Provider store={store} key="provider">
<Router routes={routes} history={appHistory} />
</Provider>
); |
@wayspurrchen on the link you provided it states:
How is hydration of initial state handled on the server? |
I am getting an error when trying to set up redux simple router.
I'm setting up redux simple router like so (excuse messy imports from various features). Where am I going wrong?
"redux-simple-router": "^2.0.1",
"react-router": "2.0.0-rc4",
This results in the following error:
Uncaught TypeError: Cannot read property 'type' of undefined
Here is the relevant source of the error - the "var type = _ref.type;"
The text was updated successfully, but these errors were encountered: