I have a BrowserRouter serving /, /login, and /logout on my website. When logged in, you access an app with the same navbar on every page and a dynamic content that holds the data/functionalities. This template component, "Main", has a HashRouter to serve the different pages of the application.
I added a search form in my navbar "CMNav" but I'm stuck using history to redirect when the user validates the form.
CMNav accesses the history of the BrowserRouter thanks to withRouter but can't see the history of the HashRouter as he was defined at the same level.
So when I type a search and hit enter key, my URL changes to /search but the redirection to the Search component is not done (as I'm playing with the wrong history object).
Any help on how to solve this issue?
My entry point is index.js.
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Redirect, Route, Switch } from "react-router-dom";
import Main from "./Main";
import Login from "./auth/login";
const Router = require("react-router");
const auth = require("./auth/auth");
ReactDOM.render(
<div>
<BrowserRouter history={Router.browserHistory}>
<Switch>
<Route
path="/login"
render={() => (auth.loggedIn() ? <Redirect to="/" /> : <Login />)}
/>
<Route
path="/logout"
render={() => {
auth.logout();
return <Redirect to="/login" />;
}}
/>
<Route
path="/"
render={() => (auth.loggedIn() ? <Main /> : <Redirect to="/login" />)}
/>
</Switch>
</BrowserRouter>
</div>,
document.getElementById("root")
);
When the user is logged he gets redirect to "/" and the "Main" component is called.
Main.jsx
import React, { Component } from "react";
import { HashRouter, Route } from "react-router-dom";
import Home from "./pages/Home";
import Search from "./pages/Search";
import CMNav from "./components/cm-nav";
class Main extends Component {
constructor(props) {
super(props);
this.state = {};
this.componentDidMount = this.componentDidMount.bind(this);
}
componentDidMount() {
// Do things
}
render() {
return (
<div>
<div className="container-fluid">
<CMNav />
<HashRouter>
<div>
<Route exact path="/" component={Home} />
<Route path="/search" component={Search} />
</div>
</HashRouter>
</div>
</div>
);
}
}
export default Main;
cm-nav.jsx
import React, { Component } from "react";
import { withRouter } from 'react-router-dom';
import { MenuItem, Nav, Navbar, NavDropdown, NavItem } from "react-bootstrap";
import TextInput from "./text-input";
class CMNav extends Component {
constructor(props) {
super(props);
this.navSearchCallback = this.navSearchCallback.bind(this);
}
navSearchCallback(searchedText) {
// Meant to be a prop
this.props.history.push({
pathname: "/#/search",
state: { searchedText: searchedText }
});
}
render() {
return (
<Navbar collapseOnSelect fluid>
<Navbar.Header>
<Navbar.Brand>
<a href="#">
<img
className={"img-thumbnail img_logo_small"}
src={"images/logo.png"}
data-holder-rendered="true"
/>
</a>
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav>
<NavItem eventKey={1} href="#search"> Recherche </NavItem>
</Nav>
<Nav pullRight>
<NavItem eventKey={1}> <TextInput callback={(param) => {this.navSearchCallback(param)}}/> </NavItem>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default withRouter(CMNav);
Nevermind, the answer is as easy as putting CMNav inside HashRouter....
<HashRouter>
<div>
<CMNav />
<Route exact path="/" component={Home} />
<Route path="/search" component={Search} />
</div>
</HashRouter>