React Router Duplicate routes on Back Button - javascript

I have a react app. It is working fine. It uses redux,react-router 3. The routes work fine, but when I press the back button, they route gets duplicated. For example from localhost:3000/admin/main which I am currently, when I go back, it goes to localhost:3000/admin/admin/main, which return not found.
Here is my routes code:
export default (
<Route path="/" component={App}>
<Route path="home" component={requireNoAuthentication(HomeContainer)} />
<Route path="login" component={requireNoAuthentication(LoginView)} />
<Route exact path="admin/user" component={requireAuthentication(UserView)} />
<Route exact path="admin/main" component={requireAuthentication(UsersListView)} />
<Route path="secure" component={requireAuthentication(CustomerView)} />
<Route exact path="*" component={DetermineAuth(NotFound)} />
</Route>
);
I also get a console error: Adjacent JSX elements must be wrapped in an enclosing tag. If anyone can help it would be great thanks!!

Your HOC wrappers (requireNoAuthentication and requireAuthentication) and using exact (I think this might a react-router v4 only feature?) might be messing with your route history. Try restructuring your routes so that all of them fall under App -- some of the routes fall under RequireAuth, while the rest are public.
As a side note: you can avoid using React.cloneElement with passed down class methods and state by using Redux instead.
routes/index.js
import React from "react";
import { browserHistory, IndexRoute, Router, Route } from "react-router";
import App from "../components/App";
import Home from "../components/Home";
import Info from "../components/Info";
import ShowPlayerRoster from "../components/ShowPlayerRoster";
import ShowPlayerStats from "../components/ShowPlayerStats";
import Schedule from "../components/Schedule";
import Sponsors from "../components/Sponsors";
import RequireAuth from "../components/RequireAuth";
export default () => (
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route component={RequireAuth}>
<IndexRoute component={Home} />
<Route path="roster" component={ShowPlayerRoster} />
<Route path="roster/:id" component={ShowPlayerStats} />
<Route path="schedule" component={Schedule} />
</Route>
<Route path="info" component={Info} />
<Route path="sponsors" component={Sponsors} />
</Route>
</Router>
);
index.js
import React from "react";
import { render } from "react-dom";
import App from "../routes";
import "uikit/dist/css/uikit.min.css";
render(<App />, document.getElementById("root"));
components/App.js
import React, { Component, Fragment } from "react";
import { browserHistory } from "react-router";
import Header from "./Header";
export default class App extends Component {
state = {
isAuthenticated: false
};
isAuthed = () => this.setState({ isAuthenticated: true });
unAuth = () =>
this.setState({ isAuthenticated: false }, () => browserHistory.push("/"));
render = () => (
<Fragment>
<Header
isAuthenticated={this.state.isAuthenticated}
unAuth={this.unAuth}
/>
{React.cloneElement(this.props.children, {
isAuthenticated: this.state.isAuthenticated,
isAuthed: this.isAuthed
})}
</Fragment>
);
}
components/RequireAuth.js
import React, { Fragment } from "react";
import Login from "./Login";
export default ({ children, isAuthenticated, isAuthed }) =>
!isAuthenticated ? (
<Login isAuthed={isAuthed} />
) : (
<Fragment>{children}</Fragment>
);

Related

React-router is not displaying component in the browser

Inside App.js:
import React, { useState } from 'react';
import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Dashboard from './components/Dashboard/Dashboard';
import Preferences from './components/Preferences/Preferences';
import Login from './components/Login/Login';
function App() {
const [token, setToken] = useState();
if(!token) {
return <Login setToken={setToken} />
}
return (
<div className="wrapper">
<h1>Application</h1>
<BrowserRouter>
<Routes>
/*<Route path="/dashboard">*/
<Route path="/dashboard" element={<Dashboard/>} /></Route>
/*<Route path="/preferences">*/
<Route path="/preferences" element={<Preferences/>} /></Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;`
Inside Dashboard.js (../src/components/Dashboard/Dashboard.js):
import React from 'react';
export default function Dashboard() {
return(
<h2>Dashboard</h2>
);
}
Url: http://localhost:3000/dashboard
I want to see the Dashboard content along with the App page content (Application and Dashboard headers) when I load the browser. But when I load the browser, it only displays the App page content and getting the same error:
"Matched leaf route at location "/dashboard" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page."
You are using Routes instead of Router. Replace it on your line 3 and in the return().
Source: React-router https://v5.reactrouter.com/web/api/Route
//...
import { BrowserRouter, Route, Router } from 'react-router-dom';
//...
return ( ...
<Router>
/*<Route path="/dashboard">*/
<Route path="/dashboard" element={<Dashboard/>} />
/*<Route path="/preferences">*/
<Route path="/preferences" element={<Preferences/>} />
</Router>
...)
export default App;
Please specify which version of React router you are using, since a lot of the functionality has changed, is it 6.4 or is still 5 ?
Either way, please remove the comments of the routes, I don't think they help at all.
if you have chosen BrowserRouter from the 6.4 version then it should be used like this
import { BrowserRouter, Route } from 'react-router-dom';
return (
<BrowserRouter>
<Route path="/" element={<RootComp />} >
<Route path="dashboard" element={<Dashboard/>} />
<Route path="preferences" element={<Preferences/>} />
</Route>
</BrowserRouter>
)
export default App;
Where <RootComp /> should have an <Outlet /> as children
import { Outlet } from 'react-router-dom';
const RootComp = () => {
return <div><Outlet /></div>
}
export default RootComp;
Again, this is for the latest React Router component, however, I would advise using createBrowserRouter() rather than the old component-based trees, this way you can programatically create and manage the routes in an Object.

React Router Not Working Like I Need It Too

Im trying to figure out how to get my navigation bar setup as most of the UI is coming together. I have setup my index.js and also a Route.js and then linked them with my different components like so:
Index.js
import React from "react";
import ReactDOM from "react-dom";
import { Auth0Provider } from "./react-auth0-spa.js";
import { useAuth0 } from "./react-auth0-spa";
import Routes from "./Routes"
import config from "./utils/auth_config.json";
import { BrowserRouter } from "react-router-dom";
// A function that routes the user to the right place
// after login
const onRedirectCallback = appState => {
history.push(
appState && appState.targetUrl
? appState.targetUrl
: window.location.pathname
);
};
ReactDOM.render(
<Auth0Provider
domain={config.domain}
client_id={config.clientId}
redirect_uri={window.location.origin}
onRedirectCallback={onRedirectCallback}
>
<BrowserRouter>
<Routes />
</BrowserRouter>
</Auth0Provider>,
document.getElementById("root")
);
Routes.js
import React, { Component } from "react";
import { Router, Route, Switch, BrowserRouter } from "react-router-dom";
import {Link } from "react-router-dom";
import Profile from "./components/user/Profile";
import PrivateRoute from "./components/user/PrivateRoute";
import history from "./utils/history.js";
import HomePage from "./modules/HomePage.js";
import ProductPage from "./modules/ProductPage";
class Routes extends Component {
render() {
return (
<Router history={history}>
<Switch>
<Route path="/" component={HomePage} />
<Route path="/ProductPage" component={ProductPage} />
<PrivateRoute path="/profile" component={Profile} />
</Switch>
</Router>
)
}
}
export default Routes;
but when i reload my site it just continues to say localhost:8080/ProductPage like its suppose to be the default, then when i manually enter localhost:8080/ and click on a button after linking it with
<Link to="ProductPage">
it will show on the tab localhost:8080/ProductPage but wont actually redirect me to the other component, i am just wondering what i am doing wrong?
Issue
You have your "home" route listed first in the Switch.
Switch
Renders the first child <Route> or <Redirect> that matches the location.
"/" is less specific and matches basically all routes, so even though the URL is "/ProductPage", "/" still matches it and HomePage is rendered.
Solution
Either move it after the other more specific routes or use the exact prop on it.
<Router history={history}>
<Switch>
<Route path="/ProductPage" component={ProductPage} />
<PrivateRoute path="/profile" component={Profile} />
<Route path="/" component={HomePage} />
</Switch>
</Router>
or
<Router history={history}>
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/ProductPage" component={ProductPage} />
<PrivateRoute path="/profile" component={Profile} />
</Switch>
</Router>

Unmounted component with react-router

I have a problem with my react router when I want to pass from a router to another.
I have a Connexion files :
import React from "react";
import {
Switch,
BrowserRouter as Router,
Route,
Redirect,
} from "react-router-dom";
import SignIn from "./Containers/Login/Login";
import Player from "./Player";
const Routes = () => {
return (
<Router>
<Switch>
<Route exact path="/" component={SignIn} />
<Route path="/app/player/" component={Player} />
<Route path="/*">
<Redirect to="/" />
</Route>
</Switch>
</Router>
);
};
export default Routes;
When I connect from "SignIn", I want to go in the next route "Player" :
import React from "react";
import {
Switch,
BrowserRouter as Router,
Route,
useRouteMatch,
} from "react-router-dom";
import Navigation from "./Navigation/PlayerNavigation";
import FillCollect from "./Containers/Collect/Collect";
import Dashboard from "./Containers/Dashboard/Dashboard";
const Player = () => {
const { path } = useRouteMatch();
console.log(path);
return (
<Router>
<Navigation />
<Switch>
<Route path={`${path}/collect/:id`} component={FillCollect} />
</Switch>
</Router>
);
};
export default Player;
(My Navigation component is my sidebar and topbar)
But when I'm connect my Navigation is displayed but not my Fill Collect ! And i have this warning :
Warning: Can't perform a React state update on a unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect clean function.
In SignIn (created by Context.Consumer)
I tried to display a minimalist component with just div but it's the same
There are a couple of problems in this
Firstly you are using a nested Router component too, which then restricts the inner Routes from listening to the router Router component
Secondly, your matchPath in parent is "/app/player/" which if you combine with the nested Route in child like ${path}/collect/:id. It becomes "/app/player//collect/:id" which is not what you indent
The working solution will be as follows
const Routes = () => {
return (
<Router>
<Switch>
<Route exact path="/" component={SignIn} />
<Route path="/app/player" component={Player} />
<Route path="/*">
<Redirect to="/" />
</Route>
</Switch>
</Router>
);
};
export default Routes;
const Player = () => {
const { path } = useRouteMatch();
console.log(path);
return (
<React.Fragment>
<Navigation />
<Switch>
<Route path={`${path}/collect/:id`} component={FillCollect} />
</Switch>
</React.Fragment>
);
};
export default Player;

Not able to render react component in react router

I have a react application.
i have problem in routing of component
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from './app';
ReactDOM.render(
<App/>,
document.getElementById("root")
);
app.jsx
Here i am routing 2 component. Login and Main component. In Main component there are many router which will use for dashboard.
My Problem : In <Switch> the 1st <Route> can render but it's not rendering from 2nd router if i hardcode in url
http://localhost:3000/#/login == rendering
http://localhost:3000/#/main = Not rendering
import React, { Component } from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch
} from 'react-router-dom';
import Login from './login';
import Main from './main';
import createBrowserHistory from 'history/createBrowserHistory';
const customHistory = createBrowserHistory();
class App extends Component {
constructor(props) {
super(props);
window.token = '';
}
render() {
return <div>
<Router>
<Switch>
<Route to="/login" component={Login} exact />
<Route to="/main" component={Main} exact/>
</Switch>
</Router>
</div>;
}
}
export default App;
main.jsx
import React, {Component} from 'react';
import ReactDOM from "react-dom";
import { HashRouter, Route, Switch } from "react-router-dom";
import indexRoutes from "routes/index.jsx";
import "bootstrap/dist/css/bootstrap.min.css";
import "./assets/css/animate.min.css";
import "./assets/sass/light-bootstrap-dashboard.css?v=1.2.0";
import "./assets/css/demo.css";
import "./assets/css/pe-icon-7-stroke.css";
import Login from './login';
class Main extends Component {
constructor(props) {
super(props);
}
render() {
return <HashRouter>
<Switch>
{indexRoutes.map((prop, key) => {
return <Route to={prop.path} component={prop.component} key={key} />;
})}
</Switch>
</HashRouter>;
}
}
export default Main;
Use
<Route path="/login" component={Login} exact />
Instead of to use path
<Route path="/login" component={Login} />
<Route path="/main" component={Main} exact/>
Use Path insted of To
Don't use exact attribute in main Route as shown below.
class App extends Component {
render() {
return <div>
<Router>
<Switch>
...
<Route to="/main" component={Main} />
</Switch>
</Router>
</div>;
}
}
There are two problems with your code
First in your app.jsx file:
<Switch>
<Route
to="/login" // <== should be path="/login"
component={Login}
exact
/>
<Route
to="/main" // <== should be path="/main"
component={Main}
exact // <== remove exact prop for the nested routes to work
/>
</Switch>
Here to prop actually belongs to the <Link/> component provided by react-router not the <Route /> component, It should be path prop.
If you want to render child routes within <Route /> component then we never use exact prop on the Parent <Route /> component.
Second in your main.jsx file:
indexRoutes.map((prop, key) => {
return (
<Route
to={prop.path} // <== should be path={prop.path}
component={prop.component}
key={key} />;
);
})
Again change to prop to path prop.

Meteor react router rendering nothing

I'm following this guide Meteor React Routing but unfortunately, my app now renders nothing (after adding routing, the app was working fine before-hand), and I can't see anything wrong
App.jsx
import React, { Component } from 'react';
import Navigation from './components/Navigation';
import LoginForm from './components/LoginForm';
export default class App extends Component {
render() {
return (
<div>
<Navigation />
<p>
<h1>Something here</h1>
</p>
</div>
);
}
}
main.js
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import { renderRoutes } from './Routes.jsx';
Meteor.startup(() => {
render(renderRoutes(), document.getElementById('app'));
});
Routes.jsx
import React from 'react';
import { render } from 'react-dom';
import { Router, Route } from 'react-router';
import createBrowserHistory from 'history/createBrowserHistory';
import App from '../imports/ui/App.jsx';
import LoginForm from '../imports/ui/components/LoginForm.jsx';
const browserHistory = createBrowserHistory();
export const renderRoutes = () => (
<Router history={browserHistory}>
<Route exact path="/" component={App} />
<Route path="/login" component={LoginForm} />
</Router>
);
..and the html
<head>
<title>Some title</title>
</head>
<body>
<div id="app"></div>
</body>
I've verified that all imports resolve. And when running meteor, there are no errors. Nor are there any errors in the console of the browser, yet there is just a blank page. Have I missed something?
You are not returning your routes.
It should be like below,
export const renderRoutes = () => (
<Router history={browserHistory}>
<Route exact path="/" component={App} />
<Route path="/login" component={LoginForm} />
</Router>
);
// or
export const renderRoutes = () => {
return (
<Router history={browserHistory}>
<Route exact path="/" component={App} />
<Route path="/login" component={LoginForm} />
</Router>
);
};
Unfortunately there was an error that wasn't being thrown in Meteor. There was an issue with my Router definition, what it should actually be is:
export const renderRoutes = () => (
<Router history={browserHistory}>
<div>
<Route exact path="/" component={App} />
<Route path="/login" component={LoginForm} />
</div>
</Router>
);
Notice the inclusion of div - as it would appear that Router can only have one child element.

Categories