Next to the Web Tips Picture
https://i.stack.imgur.com/A2OGn.png
Warning: Hash history cannot PUSH the same path; a new entry will not be added to the history stack
Tips error , This is when I click on the link again
Next to Picture is React-Router File Code...
https://i.stack.imgur.com/WgqqN.png
import { HashRouter, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import View from './containers';
import configureStore from './store/configureStore';
const store = configureStore();
const AppRouter = () => (
<Provider store={store}>
<HashRouter>
<View.App.Container>
<Route path='/' exact={true} component={View.App.Dashboard} />
<Route path='/Todo' component={View.Todo.Container} />
<Route path='/News' render={() => (
<View.News.Container>
<Route path='/News/List' render={() => (
<h2>News List Show</h2>
)} />
</View.News.Container>
)} />
</View.App.Container>
</HashRouter>
</Provider>
);
export default AppRouter;
If you use the component Link for navigation, you may want to set the prop replace on it.
https://reacttraining.com/react-router/web/api/Link/replace-bool
Related
Im trying to create a PrivateRoutes in addition to the regular routes.
After login, the page is successfully re-direct to /home, however when I tried to open /work, the page will go back to /home. all the data from state.valid is also shows "unidentified" in /work.
I figured it out that inside the privateRoutes it check if valid.isAuthenticated is true or not. However since. valid.isAuthenticated is set to false as initial value in reducer, everytime I open /home or /work, it re-render /login and then render /home or /work.
How do I fix to not to render /login before opening other pages?
Here is my PrivateRoutes.js
import React from "react";
import { useSelector } from "react-redux";
import { Navigate } from "react-router-dom";
const PrivateRoute = ({ children }) => {
const valid = useSelector((state) => state.valid);
return valid.isAuthenticated ? children : <Navigate to="/login" />;
};
export default PrivateRoute;
here is my AppRouter.js
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import PrivateRoute from "./PrivateRoute";
import App from "../components/App";
import Login from "../components/Login";
import HomePage from "../components/HomePage";
import WorkPage from "../components/WorkPage";
const AppRouter = () => (
<BrowserRouter>
<div>
<NavigationBar />
<div>
<Routes>
<Route path="/" element={<App />} exact />
<Route path="/login" element={<Login />} exact />
<Route path="/home" element={<PrivateRoute><HomePage /></PrivateRoute>} />
<Route path="/work" element={<PrivateRoute><WorkPage /></PrivateRoute>} />
</Routes>
</div>
</div>
</BrowserRouter>
);
export default AppRouter;
useEffect(() => {
if (valid.isAuthenticated) {
navigate("/home");
}
},[valid.isAuthenticated]);
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import PrivateRoute from "./PrivateRoute";
import App from "../components/App";
import Login from "../components/Login";
import HomePage from "../components/HomePage";
import WorkPage from "../components/WorkPage";
const AppRouter = () => {
useEffect(() => {
if (!valid.isAuthenticated) {
navigate("/login");
}
});
return (
<BrowserRouter>
<div>
<NavigationBar />
<div>
{valid.isAuthenticated ? <>
<Routes>
<Route path="/" element={<App />} exact />
<Route path="/home" element={<HomePage />} />
<Route path="/work" element={<WorkPage />} />
</Routes>
</>
:
<>
<Routes>
<Route path="/login" element={<Login />} exact />
</Routes>
</>
}
</div>
</div>
</BrowserRouter>
)
};
export default AppRouter;
js and facing hard time with react router dom.
I want to change the route when I click a button in my navigation drawer component.
This is my App.js component.
import { Router, Route, Switch } from "react-router-dom";
function App() {
const classes = useStyles();
return (
<Provider store={store}>
<div className={classes.root}>
<NavBar />
<Drawer />
<Router history={history}>
<Switch>
<Route path="/" exact component={Login}></Route>
<Route path="/country" exact component={Country}></Route>
<Route path="/user-create" exact component={User}></Route>
<Route path="/countries" exact component={ListView}></Route>
<Route component={NotFound}></Route>
</Switch>
</Router>
</div>
</Provider>
);
}
And here I pass history prop to the Router component.
History.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Drawer.js
import history from '../../history'
const onRoute = (path) => {
history.push("/user-create");
// props.toggleDrawer();
}
In Drawer.js it is always route to the NotFoundComponet.
Why could this happen?
In your NavBar and Drawer components include the below withRouter or the alt useHistory hook to get access to the history prop.
import { withRouter } from 'react-router'
...
this.props.history.push('/user-create')
...
export default withRouter(...
I'd put <NavBar /> and <Drawer /> inside <Router>, and do
const { push } = useHistory() // from react-router-dom
inside them, to get a reference of the push API
I've built an app with its specific router. Now I want to improve my app by coding an admin interface. The thing is, I have components (Navbar and Footer) that surround my routes (see code below).
So if I simply create an admin interface and nest it inside my existing router, my app's navbar and footer will appear on the admin pages.
I would like to code my admin interface with its own navbar and components.
Is there a way to do so ?
AppRouter.js:
import React from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory';
import LandingPage from '../ui/landing-page/LandingPage';
import App from '../ui/App';
import NotFoundPage from '../ui/NotFoundPage';
import NavBar from '../ui/NavBar';
import Footer from '../ui/Footer';
import FaqPage from '../ui/FaqPage';
import PrivacyPage from'../ui/PrivacyPage';
import LegalNoticePage from '../ui/LegalNoticePage';
const browserHistory = createBrowserHistory();
export const AppRouter = () => (
<Router history={browserHistory}>
<div>
<NavBar />
<Switch>
<Route exact path="/" component={LandingPage}/>
<Route exact path="/meals" component={App}/>
<Route exact path="/faq" component={FaqPage}/>
<Route exact path="/privacy" component={PrivacyPage}/>
<Route exact path="/legal_notice" component={LegalNoticePage}/>
<Route component={NotFoundPage}/>
</Switch>
<Footer />
</div>
</Router>
);
export default AppRouter;
Your <NavBar /> isn't surrounding your <Router>, it's surrounding your routes. Since you can nest Routers, you could have a <Route> which matches all path="/admin" and then within that put the admin-only NavBar.
You can read more about nested routes here.
Here's a code example:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Switch, Route } from "react-router-dom";
const Admin = ({ match }) => (
<React.Fragment>
<h1>admin bar</h1>
<Route path={`${match.path}/1`} render={() => <h2>one</h2>} />
<Route path={`${match.path}/2`} render={() => <h2>two</h2>} />
</React.Fragment>
);
const Other = ({ match }) => (
<React.Fragment>
<h1>other bar</h1>
<Switch>
<Route path={`${match.path}/2`} render={() => <h2>one</h2>} />
<Route path={`${match.path}/2`} render={() => <h2>two</h2>} />
</Switch>
</React.Fragment>
);
const App = () => (
<BrowserRouter>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/other" component={Other} />
</Switch>
</BrowserRouter>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
And accompanying CodeSandbox.
I have a React app that is currently using react-router#4.2.0 and I'm struggling with rendering a specific component when the URL changes.
When I try to visit /locations/new it returns with a PropTypes error from the CityList component. I have tried adding in exact to the Route component within LocationsWrapper and then Main config too, however, this then influences other routes - such as /locations to become null.
// BrowserRouter
import React from "react";
import { render } from "react-dom";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import store from "./store";
import Navbar from "./components/Core/Navbar";
import Routes from "./config/routes";
render(
<Provider store={store}>
<BrowserRouter>
<div style={{ backgroundColor: "#FCFCFC" }}>
<Navbar />
<Routes />
</div>
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
// Router config - ( Routes )
import React from "react";
import { Route, Switch } from "react-router-dom";
import Home from "../components/Home";
import Locations from "../components/Locations";
import CityList from "../components/CityList";
import CreateLocation from "../components/CreateLocation";
import Locale from "../components/Locale/index";
import Profile from "../components/Profile";
import NoMatch from "../components/Core/NoMatch";
import requireAuth from "../components/Core/HOC/Auth";
const LocationsWrapper = () => (
<div>
<Route exact path="/locations" component={Locations} />
<Route path="/locations/new" component={CreateLocation} />
<Route path="/locations/:id" component={CityList} />
</div>
);
const Main = () => (
<main>
<Switch>
<Route exact path="/" component={requireAuth(Home)} />
<Route path="/locations" component={LocationsWrapper} />
<Route path="/locale/:id" component={Locale} />
<Route path="/profile" component={requireAuth(Profile, true)} />
<Route component={NoMatch} />
</Switch>
</main>
);
export default Main;
Am I best avoiding <Switch> entirely and implementing a new method for routes that are undefined - such as 404s?
Yes, this will definitely return first
<Route path="/locations/:id" component={CityList} />
In react-router 4 there is no concept of index route, it will check each and every routes so in your defining routes are same
<Route path="/locations/new" component={CreateLocation} />
<Route path="/locations/:id" component={CityList} />
both path are same '/location/new' and '/location/:id' so /new and /:id are same params.
so at last 'CityList' will return
You can define like this
<Route path="/locations/create/new" component={CreateLocation} />
<Route path="/locations/list/:id" component={CityList} />
Pretty sure your route is not working cause you are also matching params with /locations/new with /locations/:id so then 'new' becomes Id param.
Try changing this
<Route path="/locations/new" component={CreateLocation} />
To something like this
<Route path="/locs/new" component={CreateLocation} />
Just a suggestion hope this may help
I want to pass down the history prop down from the App to the Navigation component.
When I try to do so, I get the following error message:
Failed prop type: The prop history is marked as required in Navigation, but its value is undefined.
How can I resolve this issue?
App.js:
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
const App = props => (
<Router>
<MainLayout {...props}>
<Switch>
<Route exact name="index" path="/" component={Index}/>
<Route component={NotFound}/>
</Switch>
</MainLayout>
</Router>
);
MainLayout.js:
import React from "react";
import PropTypes from "prop-types";
import Navigation from "../../components/Navigation/Navigation";
const MainLayout = props => {
const { children, authenticated, history } = props;
return (
<div>
<Navigation authenticated={authenticated} history={history} />
{children}
</div>
);
};
MainLayout.PropTypes = {
children: PropTypes.node.isRequired,
authenticated: PropTypes.bool.isRequired,
history: PropTypes.object.isRequired,
};
export default MainLayout;
SOLUTION #1:
If you simply convert <MainLayout /> to a <Route /> that renders you will have access to the history object.
<Route render={(props) =>
<MainLayout {...props}>
<Switch>
<Route exact name="index" path="/" component={Index}/>
<Route component={NotFound}/>
</Switch>
</MainLayout>
}/>
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Route.js
<App /> does not have access to history as a prop so this will never do what you are wanting <MainLayout {...props}>
SOLUTION #2
You can also reference the history object as a single exported module in your app and refer to that both React router and any other compopent / javascript file in your app.
import { Router, Switch, Route } from 'react-router-dom';
import history from './history';
const App = props => (
<Router history={history}>
<MainLayout history={history} {...props}>
<Switch>
<Route exact name="index" path="/" component={Index}/>
<Route component={NotFound}/>
</Switch>
</MainLayout>
</Router>
);
(history.js)
import createBrowserHistory from 'history/createBrowserHistory';
export default createBrowserHistory();
https://www.npmjs.com/package/history
For react-router-dom v4
In order to get Router component's prop I used the withRouter, I guess the below change should work,
export default wihtRouter(MainLayout);
This should enable the usage of props.history in MainLayout