14

I am trying to following this react router redux so I can redirect using the push('/') in my components or actions.

Tutorial: https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux

I am not sure what I missing but I am getting an error.

The error I am getting in chrome console is:

bundle.js:3090 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of Root. in Root printWarning @ bundle.js:3090

bundle.js:2684 Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

bundle.js:20893 The above error occurred in the component: in Provider (created by Root) in Root

index.js

import React from 'react';
import { render } from 'react-dom';
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import { routerReducer, routerMiddleware, push } from 'react-router-redux'
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';

import reducers from './reducers';
import Root from './root';

// Create a history of your choosing (we're using a browser history in this case)
const history = createHistory();
let middleware = [thunk, routerMiddleware(history)]

const store = createStore(
  combineReducers({
    ...reducers,
    router: routerReducer
  }),
  applyMiddleware(...middleware)
);

render(
  <Root store={store} history={history} />,
  document.getElementById('app')
);

root.js

import React from 'react';
import PropTypes from 'prop-types';
import {
  BrowserRouter as Router,
  Route,
  Link,
  Switch,
} from 'react-router-dom';
import { ConnectedRouter } from 'react-router-redux';
import { Provider } from 'react-redux';
import App from './components/app';

const Root = ({ store, history }) => (
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <div className="application-container">
      <App>
        <Switch>
        </Switch>
      </App>
      </div>
    </ConnectedRouter>
  </Provider>
);

Root.propTypes = {
  store: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired,
};

export default Root;

/reducers/index.js

import { combineReducers } from 'redux';
import users from './users';

const reducers = combineReducers({
  users,
});

export default reducers;

users.js

import Constants from '../constants';

const initialState = {
  users: [],
  fetching: false,
};

const users = (state = initialState, action) => {
  switch (action.type) {
    case Constants.LOADING_USERS:
      return {...state, fetching: true};
    default:
      return state;
  }
};

export default users;

my package.json deps:

  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-eslint": "^8.2.1",
    "babel-loader": "^7.1.2",
    "babel-plugin-react-display-name": "^2.0.0",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-react-hmre": "^1.1.1",
    "babel-preset-stage-0": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "babel-register": "^6.26.0",
    "colors": "^1.1.2",
    "compression": "^1.7.1",
    "eslint": "^4.15.0",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-plugin-babel": "^4.1.2",
    "eslint-plugin-import": "^2.8.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.5.1",
    "eslint-watch": "^3.1.3",
    "express": "^4.16.2",
    "jest": "^22.0.6",
    "node-sass": "^4.7.2",
    "npm-run-all": "^4.1.2",
    "redux-devtools": "^3.4.1",
    "sass-loader": "^6.0.6",
    "webpack": "^3.10.0",
    "webpack-dev-middleware": "^2.0.4",
    "webpack-dev-server": "^2.10.1",
    "webpack-hot-middleware": "^2.21.0"
  },
  "dependencies": {
    "axios": "^0.17.1",
    "history": "^4.7.2",
    "lodash": "^4.17.5",
    "moment": "^2.20.1",
    "react": "^16.2.0",
    "react-dnd": "^2.5.4",
    "react-dnd-html5-backend": "^2.5.4",
    "react-dom": "^16.2.0",
    "react-redux": "^5.0.6",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "react-router-redux": "^4.0.8",
    "redux": "^3.7.2",
    "redux-thunk": "^2.2.0"
  },
Blankman
  • 236,778
  • 296
  • 715
  • 1,125

2 Answers2

11

This could be an issue with dependency mismatch. The repository also mentions something regarding this:

This (react-router-redux 5.x) is the version of react-router-redux for use with react-router 4.x. Users of react-router 2.x and 3.x want to use react-router-redux found at the legacy repository.

Here is a working codesandbox set with react-router-redux 5.x and react-router 4.x for the same tutorial.

Update: Seems like you're using react-router-redux 4.x which might be causing the errors. This sandbox uses v4.x and throws errors

Divyanshu Maithani
  • 9,464
  • 1
  • 31
  • 41
1

If you are not doing a server side rendering then use BrowserRouter instead in your root.js (See above). This is inside package react-router-dom.

import { BrowserRouter } from 'react-router-dom'

I would use ConnectedRouter (from react-router-redux) in root.js file only when I am doing serverside rendering. In this case when Hydrate happens (in index.js) in will not throw errors and warnings.

OR Please try this. Correct your routing with a ConnectedSwitch as shown in below example:

const AppContainer = () => (
      <ConnectedSwitch>
        <Route exact path="/" component={() => (<h1>Home <Link to="/about">About</Link></h1>)} />
        <Route path="/about" component={() => (<h1>About <Link to="/">Home</Link></h1>)} />
      </ConnectedSwitch>
    )

const App = connect(state => ({
  location: state.location,
}))(AppContainer)

render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  document.getElementById('root'),
)

I am open for discussion. Regards.

Abhay Shiro
  • 2,320
  • 2
  • 10
  • 23