0

Short version: When the user clicks a button, I want to do something, then reroute the user. How do I do this?


Longer version:

I have nested routes (don't know if this has any effect to the problem at hand) how this is setup is described in a pretty minimal (to the best of my knowledge) example here: link to SO question

I want a button, that first does something, then reroutes the user, therefore I can't use Link. First all I saw was

use this.props.history.push('/route') for that

But then I learned that this.props.history isn't a thing anymore and is now it's own npm package. Here I got a simple explenation on how to implement what I needed.


Example of my problem:

App.js render this:

<Router history={history}>
  <div>          
    <Link to="/">
      <button>Go to home</button>
    </Link>
  <Switch>
    <Route exact path="/other" component={() => <Other/>} />
    <Route path="/" component={() => <Home/>} />
  </Switch>
  </div>
</Router>

With two top level routes, an exact path for /other that render Other and looks like this:

enter image description here

and a relative path for / that render Home and looks like this:

enter image description here

Home renders this code:

<div>
  THIS IS HOME WOO!
  <div>
      <Route exact path="/" component={() => <HomeController/>} />
      <Route exact path="/about" component={() => <About/>} />
      <Route exact path="/click-page" component={() => <ClickPage/>} />              
  </div>
</div>

Now here the default is HomeController (containing two buttons with links to about and click-page), but /about renders About and looks like this:

enter image description here

and /click-page renders ClickPage and looks like this:

enter image description here


This is where the problem starts :(

So ClickPage renders this:

<button onClick={clickHandler}>
  DO SOMETHING THEN GO TO ABOUT
</button>

where clickHandler looks like this:

function clickHandler(){
  console.log("doing stuff");
  history.push('/about');
}

history in this case is imported from another file that looks like this:

// history.js
import { createBrowserHistory } from 'history'

export default createBrowserHistory({
/* pass a configuration object here if needed */
})

which is character by character copied from the answer i mentioned earlier.

Problem is, when I click the button, this is what I see:

enter image description here

So the function is called, it does something, and then it pushes "/about" to history, but nothing happens. Why is this? Do I need to force Home to rerender?

The full example code I've used to recreate the issue is here: pastebin-link

MrJalapeno
  • 1,532
  • 3
  • 18
  • 37

3 Answers3

0

First thing is that,

this.props.history.push('/route')

is still present in the react-router4. the history prop is only available to the direct child of Router.

In case ur component is not direct child of the Router, u can export that component using the withRouter HOC, which can be imported like this

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

then, on click of button, u can do ur stuff, and use

this.props.history.push('/route')

to go to any location

Gautam Naik
  • 8,990
  • 3
  • 27
  • 42
0

You can use this.history.push in any component rendered by a Route.

Example code here: https://codesandbox.io/s/w21m5mlvyw

Colin Ricardo
  • 16,488
  • 11
  • 47
  • 80
  • Cool! Working on implementing it, I think I might have also learned a reason to use `component={ClickPage}` instead of `component={() => `. If I just remove `history={history} from `Router` and change it to `this.props.history.push` I get an error that `props` doesn't have `history`. But if I change it to be exactly your code it works. Gonna look closer as to what more is needed. – MrJalapeno Apr 21 '18 at 18:16
  • Yeah, I recommend using the `component={Component}` pattern. If it helps, feel free to mark as correct :) – Colin Ricardo Apr 21 '18 at 19:10
0

You can do it like this ..

import { Redirect } from 'react-router'
...

render() {
...

{fireRedirect && (
  <Redirect to={from || '/thank-you'}/>
)}

Update your fireRediect state after your user action is completed

This looks like something you need here.

Hokagoka
  • 139
  • 3