AVAVT
AVAVT

Reputation: 7143

react-router v4: triggering a redirect programmatically (without having to render a <Redirect / >)

I'm currently switching my web app to react. The old one is located here.

What I'm trying to do is: when an user enter a player's username into the text field and submit, the app would redirect to the corresponding route (/:username), and the text field is cleared.

In the react version, this is what I'm doing currently: https://github.com/AVAVT/g0tstats-react/blob/master/src/components/SideBar/SearchBox.js

submit(event){
    ...

    this.setState({
      redirect : true
    });

    ...
}

And

render(){
    ...
    {
          this.state.redirect && (
          <Redirect to={`/${this.state.username}`} push />
          )
    }
}

Which kinda work. But there are 2 things I don't like about it:

  1. I'm rendering an element in order to redirect. It feels stupid and roundabout. It stinks of potential bug in the future.
  2. I'm stuck with the text field not cleared. Because I if I set state.username to null the <Redirect /> component will not redirect correctly. In fact I don't have any precise control over when the redirection occur (unless I do it in another roundabout way).

I have searched for alternative, but couldn't find one. withRouter doesn't work because <SearchBox /> is not a <Route /> and doesn't receive the history props.

So how can I say "redirect me to that place NOW" in react-router v4?

Upvotes: 1

Views: 633

Answers (1)

Chaim Friedman
Chaim Friedman

Reputation: 6261

Here is an example that shows when using the withRouter HOC, the routing props get injected to components even if they are not routed to.

Here is my App.js

    class App extends Component {
      render() {
        return (
          <div className="App">
            <BrowserRouter>
              <div>
                <Route path='/test' component={Sample} />
                <Sibling />
              </div>
            </BrowserRouter >
          </div>
        );
      }
    }

export default App;

Here is my Sample.js. This is like an example container that is rendering a child.

export default class Sample extends React.Component {
    render() {
        return (
            <div>
                <span>{this.props.location.pathname}</span>
                <br />
                <Nested />
            </div>
        )
    }
}

This component can display information about the current route even without the withRouter HOC since it is being routed to.

Here is my Nested.js.

class Nested extends React.Component {
    render() {
        return (
            <div>
                <span>I am nested {this.props.location.pathname}</span>
            </div>
        )
    }
}

export default withRouter(Nested);

My nested component needs the withRouter HOC in order to display the current route.

Finally here is my Sibling.js. (This is like your example where <SearchBox /> is a sibling.)

class Sibling extends React.Component {
    render() {
        return (
            <span>{this.props.location.pathname}</span>
        )
    }
}

export default withRouter(Sibling);

Here all that is needed is to make sure that the sibling is nested within the router as you can see in my App.js, and then using the withRouter HOC it can display the current pathname.

To clarify: If a component can access the current pathname then it can also change the routes programmatically by doing this. this.props.history.push(some path).

I hope this helps.

Upvotes: 2

Related Questions