Unmounted component with react-router - javascript

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;

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 components not rendering with routes

I am using the latest version of react router. When I am using routes in my component, They are not rendering anything but When I remove the routes and use simply the component they are working fine. Not able to understand what is going wrong
This do not work and is not rendering anything on "/" or http://localhost:3000/
import React from "react";
import { BrowserRouter as Router, Route, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return (
<Router>
<Route path="/" exact>
<Users />
</Route>
<Navigate to="/" />
</Router>
);
}
export default App;
This is rendering and working fine.
import React from "react";
import { BrowserRouter as Router, Route, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return <Users />;
}
export default App;
import React, {useState} from "react";
import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
import Profiles from "./Profiles" // this is dummy
function App() {
const [state, setState] = useState(false)
return (
<Router>
<Routes>
<Route path="/" element={<Users />}/>
<Route path="/profiles" element={state ? <Profiles /> : <Navigate to="/" />} />
{/* so you redirect only if your state is false */}
</Routes>
</Router>
);
}
export default App;
It is because, You din't provide which element to render in Route. It has to be mentioned like element={<Users />}. So try like below,
import React from "react";
import { BrowserRouter as Router, Route, Routes, Navigate } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Users />} />
<Navigate to="/" />
</Routes>
</Router>
);
}
export default App;
Based on the docs, all Route components should be placed inside a Routes component, which is nested inside the BrowserRouter.
Also, I noticed you use Navigate everytime, even when you are already at the index path. I think this may cause a problem...
So, with that in mind, Change your code to
import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Users from "./user/pages/Users";
function App() {
return (
<Router>
<Routes>
<Route path="/">
<Route index element={<Users />} />
</Route>
</Routes>
</Router>
);
}
export default App;
Issue
In react-router-dom#6 the Route component renders its content on the element prop as a ReactNode, a.k.a. JSX, the only valid child of the Route component is another Route component for the case of nesting routes. The Users component should be moved to the element prop.
Also, to render a redirect to a default route, the Navigate component should also be rendered on a generic route.
Solution
Move Users component onto route's element prop.
Move the Navigate component into a generic route and pass the replace prop so issue a redirect.
Example:
function App() {
return (
<Router>
<Route path="/" element={<Users />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Router>
);
}

React Router: Component not getting displayed

I have just started with React and not able to get the router working. Below is the code for router. If I use the individual components without the router, they are displayed on the screen. But with router I don't get any text on the screen across any of the paths.
Please let me know if I am missing something. Below is the code:
import { Route } from 'react-router-dom';
import AllMeetupsPage from './pages/AllMeetups';
import NewMeetupPage from './pages/NewMeetup';
function App() {
return (
<div>
<Route path='/' exact>
<AllMeetupsPage />
</Route>
<Route path='/new-meetup'>
<NewMeetupPage />
</Route>
</div>);
}
export default App;
A route needs to be a descendent of router component. I'm not sure which version of react-router you're using, but this will be a BrowserRouter and Routes component for react-router v6 and on v4/v5 it'll be a BrowserRouter
Here's some examples:
v6:
import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";
import AllMeetupsPage from './pages/AllMeetups';
import NewMeetupPage from './pages/NewMeetup';
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path="/" exact element={<AllMeetupsPage />}/>
<Route path="/new-meetup" element={<NewMeetupPage />}/>
</Routes>
</BrowserRouter>
</div>);
}
export default App;
You missed using Switch component
import { Route , Switch } from 'react-router-dom';
function App() {
return (
<div>
<Switch>
<Route path='/' exact>
<AllMeetupsPage />
</Route>
<Route path='/new-meetup'>
<NewMeetupPage />
</Route>
</Switch>
</div>);
}
export default App;

React Router Duplicate routes on Back Button

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>
);

Why cant I separate <Switch> to a different module?

Goal
I'm trying to extract the <Switch> with its <Route>'s out to a different module.
Problem
The url is being changed to the new path, but the content doesn't (only when I refresh it changes).
I'm trying to understand what am I missing.
EDITED:
live example: https://stackblitz.com/edit/separated-switch-module
working example:
<BrowserRouter>
<div>
<Link to="/"> Home </Link>
<Link to="contacts"> Contacts </Link>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/contacts" component={Contacts} />
</Switch>
</div>
</BrowserRouter>
failing exmaple:
<BrowserRouter>
<div>
<Link to="/"> Home </Link>
<Link to="contacts"> Contacts </Link>
<SwitchedRoutes/>
</div>
</BrowserRouter>
EDITED:
SwitchedRoutes:
import React from "react";
import { observer, inject } from "mobx-react";
import { Switch, Route } from "react-router-dom";
#inject('pageStore')
#observer
export default class extends React.Component {
render(){
const {
home,
contacts
} = this.props.pageStore.pages;
return (
<Switch>
<Route exact path={home.path} render={()=> <Home />} />
<Route path={contacts.path} render={()=> <Contacts/>} />
</Switch>
)
}
}
Since react-router v4 changed an API a bit you need to give to the all underlying components such as Switch, Link and etc a router context. (Something like subscriber to the routing stuff), as soon as you disconnects the module to the separate file it loses the context.
just add this to the SwitchedRoutes.js
import React from 'react';
import { withRouter } from 'react-router'
import {Switch, Route} from 'react-router-dom';
import {inject, observer} from 'mobx-react';
const Home = () => <h1>Home</h1>;
const Contacts = () => <h1>Contents</h1>;
const switchedRouter = inject('store')(observer(props => {
const {home, contacts} = props.store.routes;
return(
<Switch>
<Route exact path={home.path} component={Home}/>
<Route path={contacts.path} component={Contacts}/>
</Switch>
);
}));
export default withRouter(switchedRouter)
we simply wrapped the component with withRouter HoC which provides us a correct react-router context.
https://separated-switch-module-j92psu.stackblitz.io

Categories