Asool
Asool

Reputation: 14189

React Router 4 and props.history.push

There's something driving me crazy in React, and I need your help. Basically, when the user clicks "My Profile", I want to redirect to the user's profile. To do that, I use the following snippet

viewProfile = () => {
    console.log('My USER ID: ', this.props.userId);
    this.props.history.push(`/profile/${this.props.userId}`);
}

This should work. However, although the URL is changing to the correct URL when 'My Profile' is clicked, the page isn't appearing. It just stays as the old page.

After googling for a while, I know it's something to do with redux ... However, I can't find a solution. (this.props.userId is coming from a Layout component, which is in turn getting it from redux store)

Here's my code:

// React
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
// Redux
import { connect } from 'react-redux';
import * as actions from '../../../store/actions/';
// Containers and Components
   ...// more imports

const styles =  // styles

class NavBar extends Component {

  handleAuthentication = () => {
    if (this.props.isAuthenticated) {
      this.props.history.push('/logout');
    } else {
      this.props.history.push('/login');
    }
  };

  viewProfile = () => {
    console.log('My USER ID: ', this.props.userId);
    this.props.history.push(`/profile/${this.props.userId}`);
  };

  render() {
    let buttons = (
      <Auxillary>
        {this.props.isAuthenticated ? (
          <RaisedButton
            label="MY PROFILE"
            primary={true}
            style={styles.button}
            onClick={this.viewProfile} // THIS IS THE METHOD
          />
        ) : null}
        <RaisedButton
          backgroundColor={grey900}
          label={this.props.isAuthenticated ? 'LOGOUT' : 'LOGIN'}
          labelColor={grey50}
          style={styles.button}
          onClick={this.handleAuthentication}
        />
      </Auxillary>
    );

    let itemSelectField = null;
    if (this.props.location.pathname === '/items') {
      itemSelectField = (
        <ItemSelectField
          onSelectTags={tags => this.props.filterItemsByTagName(tags)}
        />
      );
    }
    let bar = null;
    if (
      this.props.location.pathname !== '/login' &&
      this.props.location.pathname !== '/register'
    ) {
      bar = (
        <AppBar
          style={styles.appBar}
          title={itemSelectField}
          iconElementLeft={
            <img style={styles.logoHeight} src={Logo} alt="logo" />
          }
          iconElementRight={buttons}
        />
      );
    }
    return <Auxillary>{bar}</Auxillary>;
  }
}

const mapDispatchToProps = dispatch => {
  return {
    filterItemsByTagName: selectedTags =>
      dispatch(actions.filterItemsByTagName(selectedTags))
  };
};

export default withRouter(connect(null, mapDispatchToProps)(NavBar));

You can find the entire app here: https://github.com/Aseelaldallal/boomtown/tree/boomtown-backend-comm

I'm going crazy trying to fix this. help.

Upvotes: 2

Views: 4712

Answers (2)

RIYAJ KHAN
RIYAJ KHAN

Reputation: 15292

You need to integrate the react-router-redux.

Its look like the updated state is not reflecting in the container as redux do shallow comparison to check whether the component need to be update or not.

import {Router} from 'react-router-dom';
import { ConnectedRouter, routerReducer, routerMiddleware } from 'react-router-redux';
import createHistory from 'history/createBrowserHistory';

const history = createHistory()
const middleware = routerMiddleware(history)


const rootReducer = combineReducers({
    router: routerReducer,
  //other reducers
});

const store = createStore(rootReducer,applyMiddleware(middleware));

<Provider store={store}>
<ConnectedRouter>
 //routes
</ConnectedRouter>
</Provider>

Also,at reducers,add this snippet.

let updatedStore = JSON.parse(JSON.stringify(state));

Upvotes: 2

Tripti Rawat
Tripti Rawat

Reputation: 671

I think has to do with you using <BrowserRouter>. It creates its own history instance, and listens for changes on that. So a different instance will change the url but not update the <BrowserRouter>. Instead you can use ConnectedRouter and pass a history instance as

import createHistory from 'history/createBrowserHistory';
...
const history = createHistory();
...
<ConnectedRouter history={history}>
...
</ConnectedRouter>

Upvotes: 2

Related Questions