Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to setup redux history so I can redirect

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"
  },
like image 242
Blankman Avatar asked Feb 25 '18 16:02

Blankman


People also ask

How do I redirect a user to another route using Redux?

There are several ways to redirect a user to another route, including the history.push () method and the <Redirect /> component from react-router. In this guide, we will use a Redux action to redirect the user using the <Redirect /> component. We will dispatch an action to redirect a user to the home page after they submit a registration form.

Should you use Redux for undo history?

With Redux, however, implementing undo history is a breeze. There are three reasons for this: There are no multiple models—just a state subtree that you want to keep track of. The state is already immutable, and mutations are already described as discrete actions, which is close to the undo stack mental model.

How to programmatically create a browser history session in Redux?

The first set of things to do are with the Redux store. 1. Create a history object Technically, there’s a DOM history object for manipulating the browser’s history session. Let’s programmatically create one ourselves. ... import { createBrowserHistory } from 'history' ...

How to check if a redux action has successfully been done?

A simple solution would be to check for a state change in componentDidUpdate. Once your state has updated as a result of a successful redux action, you can compare the new props to the old and redirect if needed.


Video Answer


2 Answers

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

like image 106
Divyanshu Maithani Avatar answered Oct 17 '22 21:10

Divyanshu Maithani


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.

like image 44
Abhay Shiro Avatar answered Oct 17 '22 22:10

Abhay Shiro