EdG
EdG

Reputation: 2351

Router not navigating to next page but url changes

I have 3 pages in my react application. A login page, a homepage and a video page.

Problem: When the login button is clicked, it makes POST request successfully but doesn't navigate to next page. When clicked on login button, the url changes to required route but view doesn't change.

Tried: 1) I tried using these two things : this.context.router.push('/app') but it gives me the error saying Uncaught TypeError: Cannot read property 'router' of undefined 2) I tried using browserHistory.push('/app') but that changes the url and and not the view.

function getRoutes(store) {

    return (
        <Router history={browserHistory}>
            <Route path="/" component={LoginPage}/>
            <Route path='app' component={App}>
                <IndexRoute component={Home}/>
                <Route>
                    <Route path='/video-screen' component={VideoScreen}/>
                    <Redirect from='*' to='/'/>
                </Route>
            </Route>
        </Router>
    )
}
export default getRoutes;

Below is my index.js file which is entry point rendering Root using above routes.

window.Promise = Promise;
window.$ = window.jQuery = $;
injectTapEventPlugin();

var browserHistory = useRouterHistory(createHistory)({
    queryKey: false,
    basename: '/'
});

var initialState = window.INITIAL_STATE || {};

var store   = configureStore(initialState, browserHistory);
var routes  = getRoutes(store);
var history = syncHistoryWithStore(browserHistory, store, {
  selectLocationState: (state) => state.router
});

const ROOT_CONTAINER = document.getElementById('root');
const onRenderComplete = ()=> {
    console.timeEnd('render');
}

if ( __DEV__ ){
    window._STORE = store;
    window.React = React;
    window.ReactDOM = ReactDOM;
}
window.localStorage.debug = 'tessact:*'
window._History = history

let muiTheme = getMuiTheme(theme);

console.time('render');
match({ history, routes }, (error, redirectLocation, renderProps) => {
    ReactDOM.render(
        <MuiThemeProvider muiTheme={muiTheme}>
            <Root store={store}>
                <WithStylesContext onInsertCss={styles=> styles._insertCss()}>
                    <Router {...renderProps} />
                </WithStylesContext>
            </Root>
        </MuiThemeProvider>,
        ROOT_CONTAINER,
        onRenderComplete
    )
});

This is my login page

export default class LogInComponent extends Component {
    handleLoginButtonClick() {
        var settings = {
            "async": true,
            "crossDomain": true,
            "url": "https://trigger-backend.appspot.com/auth/login/",
            "method": "POST",
            "credentials": 'include',
            "headers": {
                "content-type": "application/x-www-form-urlencoded",
            },
            "data": {
                "password": "apurv",
                "username": "Apurv"
            },
            success: function( data, textStatus, jQxhr ){
               alert("success");
            },
        }

        $.ajax(settings).done(function (response) {
            alert(response.auth_token);
            console.log('check');
            this.context.router.push('/app')
        });

    }


    render(){
        return (
            <div className="LoginPage">
                <div className="login-page">
                    <div className="form">
                        <form className="login-form">
                            <input id="username" type="username" placeholder="username"/>
                            <input id="password" type="password" placeholder="password"/>
                            <p className="message">Not registered? <a href="#">Request Username and Password</a></p>
                        </form>
                        <button onClick={this.handleLoginButtonClick.bind(this)}>login</button>
                    </div>
                </div>
                <img className="Logo_Tessact_White" src="./dev/js/images/TESSACT_logo_white.png"/>
            </div>
        );
    }
}

Upvotes: 0

Views: 361

Answers (1)

Lyubomir
Lyubomir

Reputation: 20037

The first problem is here

$.ajax(settings).done(function (response) {
      alert(response.auth_token);
      console.log('check');
      this.context.router.push('/app')
});

this doesn't reference the component anymore, because it is in different scope. Use arrow function instead in order to reuse the component's scope

$.ajax(settings).done((response) => { // arrow function
     alert(response.auth_token);
     console.log('check');
     this.context.router.push('/app')
});

No binding of this

Until arrow functions, every new function defined its own this value (a new object in the case of a constructor, undefined in strict mode function calls, the context object if the function is called as an "object method", etc.)

Arrow function instead are called with the context in which it is defined (in this case - your component)

The other problem is here

LogInComponent.contextTypes = {
  router: React.PropTypes.func.isRequired
};

is missing, please add it.


Also, depending on the version of react-router, you might not be calling the API correctly, check out this answer for more.

Upvotes: 2

Related Questions