No routes matches for nested routing - javascript

I have simple web page and i have trouble with routing:
Index.tsx:
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<HomePage />
</React.StrictMode>
);
Homepage:
const HomePage = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Main/>}>
</Route>
<Route path="/login" element={<Login/>}>
</Route>
<Route path="/register" element={<Register/>}>
</Route>
</Routes>
</BrowserRouter>
)
};
export default HomePage;
This works as intended -> if user goes to 'www.example.com' Main component is rendered, if user goes to 'www.example.com/login Login` component is rendered and so on.
However, inside my Main component i also want to use routing:
const Main = () => {
return (
<div className="app">
<HomePageHeader/>
<Routes>
<Route path="/" element={<HomePageFeed/>}>
</Route>
<Route path="/animal" element={<AnimalSelection/>}>
</Route>
<Route path="/animal/:id" element={<Animal/>}>
</Route>
</Routes>
</div>
)
}
export default Main;
Main component has header for every content, however depending on the route i want to display different things, for / some default info, for /animal some menu and list of animals, and for /animal/:id info of specific animal.
However, when , inside HomePageFeed i try to redirect there:
let history = useNavigate(); history("/animal")
I get error: router.ts:11 No routes matched location "/animal"
What is correct way how to handle routing such as this? Is this corretly used routing?
Thanks for help!

My opinion is to have a single routing inside your application. Keep your routing part inside your App.js and share it in all your pages.
If you strictly want it to be in different component. Try wrapping the routes in the Main.tsx inside BrowserRouter might work. The problem might be because <Main /> component is not wrapped anywhere inside the BrowserRouter. Try like below,
const Main = () => {
return (
<div className="app">
<HomePageHeader/>
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePageFeed/>}>
</Route>
<Route path="/animal" element={<AnimalSelection/>}>
</Route>
<Route path="/animal/:id" element={<Animal/>}>
</Route>
</Routes>
</BrowserRouter>
</div>
)
}
export default Main;

Related

Custom components not being matched using react-router

I am trying to separate concerns with my Routes, keep my react code more organized. I am currently using react-router-dom v5.
I have an Application Routes component that has 3 children as components
AuthenticatedRoutes
PublicRoutes
Error404Route
Each component renders different routes/components, but only the first component (AuthenticatedRoutes) is being matched.
Application Routes
export const ApplicationRoutes = () => (
<Switch>
<AuthenticatedRoutes />
<PublicRoutes />
<Error404Route />
</Switch>
);
Authenticated Routes
export const AuthenticatedRoutes = () => (
<Switch>
<Route exact path='/dashboard'>
<Dashboard />
</Route>
<Route exact path='/profile'>
<Profile />
</Route>
</Switch>
);
Public Routes
export const PublicRoutes = () => (
<Switch>
<Route exact path='/about'>
<About />
</Route>
<Route exact path='/'>
<Home />
</Route>
</Switch>
);
Error Route
export const Error404Route = () => (
<Switch>
<Route>
<Error404 />
</Route>
</Switch>
);
So, was I was saying only the AuthenticatedRoutes (/dashboard and /profile) are being matched, the public routes and error404 route are not.
I thought that if you used a Switch the route will try to match the location pathname, if not, then the Error404Route will display.
Am I missing something? (sure I am)
Thanks!
Try it like this:
Application Routes
import AuthenticatedRoutes from './AuthenticatedRoutes'
import PublicRoutes from './PublicRoutes'
import Error404Route from './Error404Route'
export const ApplicationRoutes = () => (
<Switch>
{AuthenticatedRoutes}
{PublicRoutes}
{Error404Route}
</Switch>
);
Authenticated Routes
import Dashboard from './Dashboard'
import Profile from './Profile'
export const AuthenticatedRoutes = [
<Route exact path='/dashboard' component={Dashboard}/>,
<Route exact path='/profile' component={Profile}>,
];
Public Routes
import Home from './Home'
import About from './About'
export const PublicRoutes = [
<Route exact path='/' component={Home}/>,
<Route exact path='/about' component={About}>,
];
Error Routes
import Error404 from './Error404'
export const Error404Route = [
<Route exact path='/' component={Error404}/>,
];

React Router content not load when refresh forward or manually input

I am new to React and getting familiarize with React Router. I divided the application into 2 main route since each use a different style: the Splash path is when the user first enter which contain the Splashscreen, Login and Register page; the Menu path is shown after the user is logined. Currently I am working on the Splash route but stumble on a few problem. The Splashscreen contain 1 button that go to the Login Screen. When I click on the button it worked fined, but if I refresh the login page, go back to the Spashscreen and forward, or manually enter the address, the page turn out blank. I tried using HashRouter and it worked, but some suggested that it should only be used on Dev server and not production. I don't use Webpack so I cannot make historyApiFallback: true and the application is running on localhost.
Below are my current code:
App.js:
import React from 'react';
import './App.css';
import SplashTemplate from './component/Template/SplashTemplate';
import {
BrowserRouter as Router,
Switch,
Route
} from "react-router-dom";
function App() {
return (
<Router>
<div className="App">
<Switch>
<Route path="/" exact={true}>
<SplashTemplate/>
</Route>
</Switch>
</div>
</Router>
);
}
export default App;
SplashTemplate.js:
import React from 'react';
import Splash from '../Splash/Splash';
import LoginForm from '../LoginForm/LoginForm';
import RegistrationForm from '../RegistrationForm/RegistrationForm';
import '../Template/SplashTemplate.css';
import { BrowserRouter, Route, Switch } from "react-router-dom";
function SplashTemplate() {
return(
<div className="background">
<BrowserRouter>
<Switch>
<Route exact path="/" component={Splash} />
<Route path="/login" component={LoginForm} />
<Route path="/register" component={RegistrationForm}/>
</Switch>
</BrowserRouter>
</div>
);
}
export default SplashTemplate;
Splash.js:
import React from 'react';
import {
BrowserRouter as Router,
Link
} from "react-router-dom";
function Splash() {
return(
<div className="container">
<Link to="/login">
<button className="splashButton">Login</button>
</Link>
</div>
);
}
export default Splash;
Anyone can suggest a solution? I have try the above mention but still not the answer I am looking for.
Update
Thanks to Danilo Venticinque answer I have reformatted the App.js file to:
function App() {
return (
<Router>
<div className="App">
<Switch>
<SplashTemplate>
<Route exact path="/" component={Splash}/>
<Route path="/login" component={LoginForm}/>
<Route path="/register" component={RegistrationForm}/>
</SplashTemplate>
<MainTemplate>
<Route path="/mainmenu" component={MainMenu}/>
</MainTemplate>
</Switch>
</div>
</Router>
);
}
And changed the SplashTemplate.js to:
class SplashTemplate extends Component {
render(){
return(
<div className="background">{this.props.children}</div>
);
};
}
It seem to work for the Splash path but now the problem show up in the Menu path where if the route is input manually (http://localhost:3000/mainmenu) the template for the Menu did not show up but instead the Splash template did. What am I doing wrong here?
Your problem is in the App.js routing. It's rendering the SplashTemplate component (which contains the other routes) only when the exact path is /. So, if you launch the page with /login, SplashTemplate doesn't get rendered (actually, nothing does) and there's no router to serve your other routes.
I would suggest moving the routes into a single component or changing the App.js routing logic so that it would still display SplashTemplate for /login and other desired routes.
So after digging around and following both React Router V4 Routers with Master Pages / Templates and React Router v5.0 Nested Routes I was able to come up with a solution. First, move all the Routing to a seperate file call Route.js and import it to App.js. Since we need to seperate the two path we will put the routing in 2 different functions and call them in a main function like below:
Route.js
...
function LayoutRoute() {
return (
<Switch>
<Route path="/splash" component={SplashLayout} />
<Route path="/main" component={MainLayout} />
<Route path="/" component={NotFound} />
</Switch>
);
}
function SplashLayout() {
return (
<SplashTemplate>
<Route path="/splash/splash" exact component={Splash} />
<Route path="/splash/login" exact component={LoginForm} />
<Route path="/splash/register" exact component={RegistrationForm} />
<Redirect from="/splash" to="/splash/splash" exact />
<Route />
</SplashTemplate>
);
}
function MainLayout() {
return (
<MainTemplate>
<Route path="/main/menu" exact component={MainMenu} />
<Redirect from="/main" to="/main/menu" exact />
<Route />
</MainTemplate>
);
}
const NotFound = () => <h1>Not Found</h1>;
export default LayoutRoute;
The App.js can just call Route:
function App() {
return (
<Router>
<LayoutRoute></LayoutRoute>
</Router>
);
}
And the Template file:
SplashTemplate.js
class SplashTemplate extends Component {
render(){
return(
<div className="background">{this.props.children}</div>
);
};
}
This can help achive seperated Layout for each path of the website/app needed and make sure the page is rendered when entered manually or refresh.

React Router add condition if route is not present

I am new to the react-redux. Here I am using the following thing for showing the 404 not found if the given route does not matches.
now, In this
My App.js
class App extends React.Component {
render() {
return (
<Provider store={store}>
<div className="container-fluid">
<Header />
<Main />
</div>
</Provider>
)
}
}
My Main.js
render() {
return (
<div>
<Router history={history}>
<div>
{this.props.isFetching && <Loading />}
<Switch>
<PrivateRoute exact path="/" component={LandingScreen} />
<PrivateRoute exact path="/quiz-setup" component={QuizSetupMain} />
<PrivateRoute exact path="/quiz-questions" component={FetchedQuestionComponent} />
<Route exact path="/login" component={LoginComponent} />
<Route exact path="/*" component={NotFound} something="foo" />
</Switch>
</div>
</Router>
</div>
)
}
}
NotFound.js
import React from 'react';
export default class NotFound extends React.Component {
render() {
return (
<h1>Something Went Wrong</h1>
);
}
}
Now , here when user hits any route which is not present then it shows that 404 not found, but it also shows the header part as well. I know that , its because I have rendered both header and main in the app.js file, and not found is in the main, but is there any way to not show that header , if the route is not matched . thanks
You can add function, which returns Component after Header.
for example:
const withHeader = (Component) => {
return class withHeaderComponent extends React.Component{ render() { return (<div><Header /><Component /></div>)}}
}
after creating this function, you can use it like,
<Route exact path="/login" component={withHeader(LoginComponent)} />.
So you are able to add header for Routes you want.
<Route component={NotFound}/>
Now your 404 will be without Header !
Let me know if you face difficulties.
You can use the component of dynamic components.
The idea is, every route path that is called, navigates through a common component which invokes suitable behaviour based on the component called. For example -
<PrivateRoute exact path="/" component={CustomComponent} />
and then pass props accordingly to determine, which screen has to render the header component.
So, essentially, your code will look something like this -
class App extends React.Component {
render() {
return (
<Provider store={store}>
<div className="container-fluid">
<Main />
</div>
</Provider>
)
}
}
and the <Header/> component will be called in custom component based on appropriate conditions that you put forward
Hope it helps :)
You can also use a wildcard to redirect people to not found page the route is not accessible.
import React from 'react';
import { Switch } from 'react-router';
import { BrowserRouter , Route ) from 'react-router-dom;
import NotFound from './NotFound';
const routes = (
<BrowserRouter>
<Switch>
<Route path="*" component={NotFound}/>
</Switch>
</BrowserRouter>
)

How to use different routes with react?

Could anyone help me with this question?
I'm a bit lost when using different routes containing subroutes.
I am trying to add routes with different paths.
I would like to have a default route with all the features and an alternate Event route separately.
From now on I am grateful for the attention and thank you very much.
index.js
Contains the two different routes. Layout and Event.
The Route Layout contains another Routes component inside.
const Root = (
<BrowserRouter>
<Route component={App}>
<Route component={Layout}/>
</Route>
<Route path="/event/:id" component={Event}/>
</BrowserRouter>
)
ReactDOM.render(Root , document.getElementById('root'));
App.js
Component to be loaded. Layout or Event
class App extends Component {
render() {
const { children } = this.props;
return (
<div>{children}</div>
);
}
}
export default App;
RouterLayout.js --> This route is a subroute that is inside the Layout
const Router = () => (
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/about' component={About}/>
</Switch>
)
export default Router
Layout.js
class Layout extends Component {
render() {
const { children } = this.props;
return (
<Content className="column is-8 content-page">
<RouterLayout/>
<div>{children}</div>
</Content>
);
}
}
export default Layout;
I was able to solve this way
<BrowserRouter>
<div>
<Route exact path="/page/*" component={Layout}/>
<Route exact path="/event/:id" component={EmptyLayout}/>
</div>
</BrowserRouter>

Problems with routes with react router and radium

I'm working on a website on reactJS. I use radium and react router for the routes.
I have a lot of problems with routes...
On my main page there is a fixed nav bar menu with a link to the documentation page.
On this documentation page I also have this bar but to access to other links I have to click 2 times to get there..
class App extends Component {
render() {
return (
<Router history={hashHistory}>
<Switch>
<Route exact path="/" component={LandingPage}/>
<Route path="/documentation" component={DocumentationRoutes}/>
<Route path="/blog" component={OnContrustion}/>
<Route path="/contactus" component={OnContrustion}/>
</Switch>
</Router>
);
}
}
export default App;
Here is the DocumentationRoutes:
class DocumentationRoutes extends Component {
render() {
return (
<Router history={hashHistory}>
<Switch>
<Route path="/documentation" component={Documentation}/>
<IndexRoute component={Documentation} />
</Switch>
</Router>
);
}
}
export default DocumentationRoutes;
and the documentation :
class Documentation extends Component {
render() {
return (
<VerticalLayout>
<StretchLayout>
<NavBar />
</StretchLayout>
<StretchLayout margin="20">
<CenterLayout>
<SubTitle>Documentation</SubTitle>
</CenterLayout>
<DocMenu />
</StretchLayout>
</VerticalLayout>
);
}
}
export default Documentation;
Is it the right way to use react router ?
What can I do to be redirected after only one click ?
On the first click, the url change correctly but not the page.
Thanks,
You only need to use the Router component in the initial routes definition. Your DocumentationRoutes component should be:
Also in react-router v4 IndexRoute no longer exists.
class DocumentationRoutes extends Component {
render() {
return (
<Switch>
<Route path="/documentation" component={Documentation}/>
<Route component={Documentation} />
</Switch>
);
}
}
export default DocumentationRoutes;

Categories