connected-react-router icon indicating copy to clipboard operation
connected-react-router copied to clipboard

Uncaught TypeError: Cannot read property 'location' of undefined upgrading from react-router-redux

Open colin-byrne-1 opened this issue 5 years ago • 6 comments

I am updating from react-router-redux, and keep getting Uncaught TypeError: Cannot read property 'location' of undefined. I am not sure if this is a bug (I see similar errors caused by package version compatabilities, but mine look OK), or if my implementation of proptypes needs to change, or another issue is at play.

//package.json

    "prop-types": "15.7.2",
    "react": "16.8.6",
    "react-dom": "16.8.6",
    "react-redux": "6.0.0",
    "redux": "4.0.1",
    "redux-thunk": "2.2.0",

//app.js

import React from 'react';
import { connect } from 'react-redux';
import { push } from 'connected-react-router'
import classNames from 'classnames';
import PropTypes from 'prop-types';

class App extends React.Component {
    static propTypes = {
        isAuthenticated: PropTypes.bool.isRequired,
        isAdmin: PropTypes.bool.isRequired,
        children: PropTypes.shape().isRequired,
        dispatch: PropTypes.func.isRequired,
        location: PropTypes.shape({
            pathname: PropTypes.string
        })
    };

    static defaultProps = {
        location: undefined
    };

    logout = () => {
        this.props.dispatch(authLogoutAndRedirect());
    };

    goToIndex = () => {
        this.props.dispatch(push('/'));
    };

    goToLogin = () => {
        this.props.dispatch(push('/login'));
    };

    render() {
        const homeClass = classNames({
            active: this.props.location && this.props.location.pathname === '/'
        });
        const protectedClass = classNames({
            active: this.props.location && this.props.location.pathname === '/policy_controls'
        });
        const loginClass = classNames({
            active: this.props.location && this.props.location.pathname === '/login'
        });

        return (
            <div className="app">
                <nav className="navbar navbar-default">
                    ...
                </nav>
                <div>
                    {this.props.children}
                </div>
            </div>
        );
    }
}

const mapStateToProps = (state, ownProps) => {
    return {
        isAuthenticated: state.auth.isAuthenticated,
        isAdmin: state.auth.isAdmin,
        location: state.router.location.pathname,    
        pathname: state.router.location.pathname,
        search: state.router.location.search,
        hash: state.router.location.hash,
    };
};

export default connect(mapStateToProps)(App);
export { App as AppNotConnected };


//reducers/index.js

import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router'
import authReducer from './auth';
import dataReducer from './data';


export default (history) => combineReducers({
    router: connectRouter(history),
    auth: authReducer,
    data: dataReducer,
});`

//index.js

import React from 'react';
import ReactDOM from 'react-dom';
import createHistory from 'history/createBrowserHistory';

import { authLoginUserSuccess } from './actions/auth';
import Root from './containers/Root/Root';
import configureStore from './store/configureStore';


const initialState = {};
const target = document.getElementById('root');

const history = createHistory();
const store = configureStore(initialState, history);

const node = (
    <Root store={store} history={history} />
);

const token = sessionStorage.getItem('token');
let user = {};
try {
    user = JSON.parse(sessionStorage.getItem('user'));
} catch (e) {
    // Failed to parse
}

if (token !== null) {
    store.dispatch(authLoginUserSuccess(token, user));
}

ReactDOM.render(node, target);

//store/configurestore.js

/* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": true}] */

import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';

import { createBrowserHistory } from 'history'
import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import createRootReducer from '../reducers'

import rootReducer from '../reducers';
import DevTools from '../containers/Root/DevTools';

export const history = createBrowserHistory()

export default function configureStore(initialState, history) {
    const logger = createLogger();

    // Build the middleware for intercepting and dispatching navigation actions
    const reduxRouterMiddleware = routerMiddleware(history);

    const middleware = applyMiddleware(thunk, logger, reduxRouterMiddleware);

    const middlewareWithDevTools = compose(
        middleware,
        DevTools.instrument()
    );

    // Add the reducer to your store on the `router` key
    // Also apply our middleware for navigating
    const store = createStore(createRootReducer(history), initialState, middlewareWithDevTools);

    if (module.hot) {
        module.hot
            .accept('../reducers', () => {
                const nextRootReducer = require('../reducers/index'); // eslint-disable-line global-require

                store.replaceReducer(nextRootReducer);
            });
    }

    return store;
}

colin-byrne-1 avatar Jul 02 '19 18:07 colin-byrne-1

+1 @cobyrne09 - did you find a solution to this?

SavageWilliam avatar Jan 09 '20 16:01 SavageWilliam

@SavageWilliam I ended up rolling back a couple packages, and haven't had any trouble. I would try rolling back react-router-redux before redux or redux-thunk. I am guessing the only one that matters is react-router-redux. I haven't had any issues with the alpha version. That said, I am sure something is going to force me to update sooner or later and I'll be sure to check back in on this thread when it does.

here are my current versions:

"prop-types": "15.7.2",
"react": "16.8.4",
"react-dom": "16.8.4",
 "react-router-redux": "5.0.0-alpha.9",
 "redux": "3.7.2",
 "redux-thunk": "2.2.0",

colin-byrne-1 avatar Jan 10 '20 06:01 colin-byrne-1

+1

Am also facing this issue

mohantorrez avatar Feb 20 '20 14:02 mohantorrez

Any solution for this issue ?

Mickaz89 avatar Apr 26 '20 10:04 Mickaz89

I don't have a proper solution for this, but I do have a hack that worked for me.

let history = { location: null };

if (typeof window === 'object') {
  history = createBrowserHistory();
}

caleyshemc avatar Apr 27 '20 03:04 caleyshemc

I had the same issue today when I tried to migrate from react-router-redux to connected-react router. For me the solution was that you need to provide the history param also in the hot reload part of your code.

if (module.hot) {
        module.hot
            .accept('../reducers', () => {
                const nextRootReducer = require('../reducers/index');
                store.replaceReducer(nextRootReducer(history));
            });
    }

There is also an example here: link

szkkteam avatar Nov 04 '20 06:11 szkkteam