Dragonsnap
Dragonsnap

Reputation: 953

React-Router: Programatically routing to a route from the root element

I am trying to route my application so that when it is any route, say / or /listing/foo, I can use the navbar's textbox to search to navigate to /search/${search-term}. However, the conventional methods for programmatically routing use history.push which isn't available in the root element, since the navbar is technically outside the Switch element.

Here's the example code:

import {
    HashRouter as Router,
    Switch,
    Route,
    NavLink as Link,
    Redirect
} from 'react-router-dom';
import React from 'react';

class App extends React.Component{
    constructor(){
        this.state = {
            searchTerm: '',
        }
    }

    render(){
        return(
            <>
                <nav>
                    <input className="input" type="text" placeholder="Search listings..." onChange={e => this.startSearching(e)} value={this.state.searchTerm}/>
                </nav>
                <Switch>
                    <Route exact path='/' component={Home} />
                    <Route path='/search/:searchTerm' component={Search} />
                </Switch>
            </>
        )
    }

    startSearching(){
        this.setState({
            searchTerm: e.target.value
        });

        // Omitted debouncing methods
        return (<Redirect push to=`/search/${this.state.searchTerm}` />); // Doesn't work
        this.props.history.push(`/search/${this.state.searchTerm}`) // this.props is undefined
    }
}

What should I do to switch the page inside the <Switch>?

Upvotes: 1

Views: 47

Answers (1)

dacopan
dacopan

Reputation: 61

You can wrap your nav component with the withRouter so in your component you can use the history.push

import React from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router";

// A simple component that shows the pathname of the current location
class Navbar extends React.Component {
    static propTypes = {
      match: PropTypes.object.isRequired,
      location: PropTypes.object.isRequired,
      history: PropTypes.object.isRequired
};

  render() {
    const { match, location, history } = this.props;

    return <div>You are now at {location.pathname}</div>;
  }
}

// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const NavbarWithRouter = withRouter(Navbar);

see more detail at https://reactrouter.com/web/api/withRouter

Upvotes: 1

Related Questions