off_the_rails
off_the_rails

Reputation: 13

Unsure how to implement history.push with react-router v4

I am playing around with react-router v4 and not sure how to push a user to a new route using history.push, and have resorted to using redirects inside my routes to achieve the same result.

I'd like to use the logInAndPush() method in my LoginPage component to push a newly logged in user to the /private_page route instead of using the redirect logic inside the /login_page route. I've tried approaches with withRouter and history but without success.

(FYI the code below can be pasted into App.js of a create-react-app app with react-router-dom installed)

import React, { Component } from 'react';
import { BrowserRouter, Link, Redirect, Route, Switch } from 'react-router-dom';
import './App.css';

class App extends Component {
  state = { loggedIn: false };
  logIn = () => { this.setState({ loggedIn: true }); };
  logOut = () => { this.setState({ loggedIn: false }); };
  render() { return <Home loggedIn={this.state.loggedIn} logIn={this.logIn} logOut={this.logOut} />; }
}

const Home = ({ loggedIn, logIn, logOut }) => (
  <BrowserRouter>
    <div style={{ padding: 50 }}>
      <h2>Routing with React-Router</h2>
      <hr /><Navigation loggedIn={loggedIn} logOut={logOut} /><hr />
      <Switch>
        <Route
          path="/private_page"
          render={() => (
            loggedIn === true ? (
              <PrivatePage />
            ) : (
              <Redirect to="/login_page" />
            )
          )}
        />
        <Route path="/public_page" component={PublicPage} />
        <Route
          path="/login_page"
          render={() => (
            loggedIn === false ? (
              <LoginPage logIn={logIn} />
            ) : (
              <Redirect to="/private_page" />
            )
          )}
        />
        <Route exact path="/" render={() => <Redirect to="/public_page" />}/>
      </Switch>
    </div>
  </BrowserRouter>
);

const PrivatePage = () => <h4>This Is The Private Page</h4>;

const PublicPage = () => <h4>This Is The Public Page</h4>;

const LoginPage = ({ logIn }) => {
  const logInAndPush = async () => {
    await logIn();
    // push user to /private_page
  }
  return (
    <div>
      <h4>Click on button to logIn</h4>
      <button onClick={logInAndPush}>logIn</button>
    </div>
  );
};

const Navigation = ({ loggedIn, logOut }) => {
  const logInLink = loggedIn ? (
    <button onClick={logOut}>logOut</button>
  ) : (
    <Link to="/login_page">Login Page</Link>
  );

  return (
    <nav>
      <Link to="/private_page">Private Page</Link><br />
      <Link to="/public_page">Public Page</Link><br />
      {logInLink}
    </nav>
  );
};

export default App;

Upvotes: 1

Views: 668

Answers (1)

tgreen
tgreen

Reputation: 1926

If you spread props into the login page you will then have access to react-routers history. You can then use that to push the new route.

import React, { Component } from 'react';
import { BrowserRouter, Link, Redirect, Route, Switch } from 'react-router-dom';
import './App.css';

class App extends Component {
  state = { loggedIn: false };
  logIn = () => { this.setState({ loggedIn: true }); };
  logOut = () => { this.setState({ loggedIn: false }); };
  render() { return <Home loggedIn={this.state.loggedIn} logIn={this.logIn} logOut={this.logOut} />; }
}

const Home = ({ loggedIn, logIn, logOut }) => (
  <BrowserRouter>
    <div style={{ padding: 50 }}>
      <h2>Routing with React-Router</h2>
      <hr /><Navigation loggedIn={loggedIn} logOut={logOut} /><hr />
      <Switch>
        <Route
          path="/private_page"
          render={() => (
            loggedIn === true ? (
              <PrivatePage />
            ) : (
              <Redirect to="/login_page" />
            )
          )}
        />
        <Route path="/public_page" component={PublicPage} />
        <Route
          path="/login_page"
          render={(props) => (
            loggedIn === false ? (
              <LoginPage logIn={logIn} {...props} />
            ) : (
              <Redirect to="/private_page" />
            )
          )}
        />
        <Route exact path="/" render={() => <Redirect to="/public_page" />}/>
      </Switch>
    </div>
  </BrowserRouter>
);

const PrivatePage = () => <h4>This Is The Private Page</h4>;

const PublicPage = () => <h4>This Is The Public Page</h4>;

const LoginPage = ({ logIn, history }) => {
  const logInAndPush = async () => {
    await logIn();
    history.push('/private_page')
    // push user to /private_page
  }
  return (
    <div>
      <h4>Click on button to logIn</h4>
      <button onClick={logInAndPush}>logIn</button>
    </div>
  );
};

const Navigation = ({ loggedIn, logOut }) => {
  const logInLink = loggedIn ? (
    <button onClick={logOut}>logOut</button>
  ) : (
    <Link to="/login_page">Login Page</Link>
  );

  return (
    <nav>
      <Link to="/private_page">Private Page</Link><br />
      <Link to="/public_page">Public Page</Link><br />
      {logInLink}
    </nav>
  );
};

export default App;

Upvotes: 1

Related Questions