Easy way to separate my protectedroute to different file in react - reactjs

I am looking for a way to separate my protectedroute from a app.js. Everything works well in my code. But if the module become to big its hard to read and manage app.js
I am looking to separate my protected routes to some component so it works here very well.
My app.js right now look like this way
import React, { useState } from 'react';
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useRouteMatch,
useParams,
HashRouter,
BrowserRouter,
Redirect
} from "react-router-dom";
import ReactDOM from 'react-dom';
//import useToken from './Routes/UseToken';
import Login from './Login/Login';
import Dashboard from './Dashboard/Dashboard';
import Customer from './Customer/Customer';
import ProtectedRoute from './Routes/ProtectedRoute';
function App() {
return (
<>
{/** use HasRouter but that will make # in the browser */}
{/*<HashRouter>*/}
<BrowserRouter basename='/invoice/webapps/'>
<Switch>
<Route path="/login"><Login /></Route>
<ProtectedRoute path="/dashboard"><Dashboard /></ProtectedRoute>
<ProtectedRoute path="/customer"><Customer/></ProtectedRoute>
<Route exact path="/"><Redirect exact from="/" to="dashboard" /></Route>
<Route path="*"><Redirect from="/" to="dashboard" /></Route>
</Switch>
</BrowserRouter>
{/** </HashRouter>*/}
{/** use HasRouter but that will make # in the browser */}
</>
);
}
export default App;
if (document.getElementById('app')) {
ReactDOM.render(<App />, document.getElementById('app'));
}
i want to separate these
<ProtectedRoute path="/dashboard"><Dashboard /></ProtectedRoute>
<ProtectedRoute path="/customer"><Customer/></ProtectedRoute>

You can create a file route.js export and object like this
const routes = [
{component: A, path: '/a'},
{component: B, path: '/b', isProtected: true}
]
and in App.js you can use routes.map(route => ()) for rendering them.
<BrowserRouter basename='/invoice/webapps/'>
{routes.map((route, index) =>
route.isProtected
? <ProtectedRoute path={route.path} key={index}><route.component/></ProtectedRoute>
: <Route path={route.path} key={index}><route.component/> </Route>
}
</BrowserRouter>
There may be some syntax errors, so I suggest you understanding my idea instead of copying.

Related

React Page won't load unless refresh

I am trying to implement a dynamic route from my app.js.
I have 2 pages. HomePage.js and ReportPageLayout.js.
When I try to navigate from HomePage to ReportPage, I am getting a status= cancelled.
Image of Network tab
When i refresh the page in the browser, the data is fetched and rendered.Image status=200 and component rendered on dom
Here is my app.js file
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Homepage from './pages/Homepage';
import ReportPage from './pages/ReportPageLayout';
export default function App() {
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={Homepage} />
<Route path="/:id" component={ReportPage} />
</Switch>
</Router>
</div>
);
}
Please help. Thank you in advance.
As far as I know (not that much), in router-dom v5 you should nest the target component and not as an argument
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Homepage from './pages/Homepage';
import ReportPage from './pages/ReportPageLayout';
export default function App() {
return (
<Fragment>
<Switch>
<Route exact path="/">
<Homepage/>
</Route>
<Route path="/:id">
<ReportPage/>
</Route>
</Switch>
</Fragment>
);
}
Furthermore, if you use suspense or importing data from, you should always create a fallback.
I had the same thing here
Delay in loading the array crushs the app

How to create seperate component just for routes using react router?

like the title says I need to create separate component where I will store routes for my project. This is what I have done in App.js component:
<Router>
<Switch>
<Route path="/" exact />
<Route path="/messages/messagelist" exact />
<Route path="/messages/ceostats" exact />
<Route path="/resourcem/categories" exact />
<Route path="/resourcem/subcategories" exact />
<Route path="/resourcem/resources" exact />
<Route path="/surveys" exact />
<Route path="/userm/users" exact />
<Route path="/userm/usergroups" exact />
</Switch>
</Router>
What I need to do now, is to extract them for example in separate component let's call it Route.js. How do I do that?
I prefer to separate the RouterProvider in this way:
First, let create a RouterProvider.js:
import React from 'react';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
function RouterProvider() {
return (
<Router>
<Switch>
// Routes
</Switch>
</Router>
)
}
export default RouterProvider;
Now, create a routes.js file:
import HomePage from 'pages/home';
import AboutUsPage from 'pages/aboutUs';
const routes = [
{
path: '/home',
component: HomePage,
exact: true
},
{
path: '/aboutUs',
component: AboutUsPage,
exact: true
},
// and so on for other routes in your project
]
export default routes;
Back to the RouterProvder.js and import the routes object and use it:
import React from 'react';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import routes from 'path/to/routes' // ---> import from routes.js file
function RouterProvider() {
return (
<Router>
<Switch>
{
routes.map(route =>
<Route path={route.path} component={route.component} exact={route.exact} />
)
}
</Switch>
</Router>
)
}
export default RouterProvider;
Finally, add the RouterProvider as the last layer in the App.js file:
import RouterProvider from 'path/to/providers/routerProvider'
function App() {
return (
<ReduxProvdier>
<RouterProvider/>
</ReduxProvider>
)
}
Note: ReduxProvider is just an example of other providers in your application like Toast provider or Network provider.
Note: creating routes object in routes.js is not useful in all cases for example if you wanna use Suspense/Lazy it's not working as your expectation.
<Route path="/" component = { ... } exact /> // read docs for more info
https://reactrouter.com/web/api/Route/component

React Router not rendering component at path, returns blank page with correct pathing

React-Router appears to be working in my app except for the fact that I am getting a blank page instead of my component, even though it is directed to the proper path.
I'm scanning the documentation but I can't resolve the issue on my own after looking it over and searching Google/this site.
I had tried...
Making it so that the router.js file just contained the routes only to get the same results. Specifying exact path as well when doing so.
Reinstalling react-router-dom into the component in case there was an error when it downloaded.
Removing the provider in case that was the issue
Placing the code in the router file directly in the App.js file between the provider component tags
These are the files involved.
Router.js
import React from 'react';
import {Route, Switch, Redirect} from 'react-router-dom';
import LandingPage from '../scenes/LandingPage';
import CityPage from '../scenes/CityPage';
const Router = () => {
return (
<Switch>
<Redirect from='/' to='/landing' />
<Route path='/landing' component={LandingPage} />
<Route path='/citypage' component={CityPage} />
</Switch>
);
}
export default Router;
App.js
import React from "react";
import { BrowserRouter } from "react-router-dom";
import Router from "./services/Router";
import ChosenCityContextProvider from "./services/context/ChosenCityContext";
const App = () => {
return (
<BrowserRouter>
<ChosenCityContextProvider>
<Router />
</ChosenCityContextProvider>
</BrowserRouter>
);
};
export default App;
No error messages accompany the rendering of the site. Aside from the blank page, everything else appears to be working. In the React Dev tools, it states that the Router.Consumer has an object which is revealed to empty when expanded.
What is wrong with my code?
https://codesandbox.io/s/youthful-maxwell-rch1k?fontsize=14
Above is sandbox of code. I have the same issue here
I'm not certain why exactly this fixes the issue, but I've run into this on a work project so knew it worked.
If you add exact into the redirect element it forces the correct behavior.
import React from 'react';
import {Route, Switch, Redirect} from 'react-router-dom';
import LandingPage from '../scenes/LandingPage';
import CityPage from '../scenes/CityPage';
const Router = () => {
return (
<Switch>
<Redirect exact from='/' to='/landing' />
<Route path='/landing' component={LandingPage} />
<Route path='/citypage' component={CityPage} />
</Switch>
);
}
export default Router;
I tried this and it worked. I'm not sure why before it didn't. If anyone has an explanation please let me know because I am trying to learn what I did wrong initially.
<Route render={() => <Redirect from='/' to='/landing' />} />
I added the above, so my router file looked like this.
import React from 'react';
import {Route, Switch, Redirect} from 'react-router-dom';
import LandingPage from '../scenes/LandingPage';
import CityPage from '../scenes/CityPage';
const Router = () => {
return (
<Switch>
<Route path='/landing' component={LandingPage} />
<Route path='/citypage' component={CityPage} />
<Route render={() => <Redirect from='/' to='/landing' />} />
</Switch>
);
}
export default Router;
#DLowther has also showed me another solution
import React from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import Page from "./Page";
import Home from "./Home";
const Router = () => {
return (
<Switch>
<Redirect exact from="/" to="/home" />
<Route path="/home" component={Home} />
<Route path="/page" component={Page} />
</Switch>
);
};
export default Router;
I would like to credit this individual for answering my question

How can I separate my app with react admin?

I have my application that works with a hash router with routes like "login" "register" "dashboard" and I would like to integrate react-admin. I would like to use react admin on my /admin route.
What I do:
App.js
import React, {Component} from 'react';
import {HashRouter as Router, Route} from 'react-router-dom';
import {Provider} from 'react-redux'
import Store from './store/configureStore'
import RegisterView from "./view/RegisterView"
import LoginView from "./view/LoginView"
import DashboardView from "./view/DashboardView"
import AdminView from "./view/AdminView"
import jsonServerProvider from "ra-data-json-server";
import { Admin, Resource, BooleanField } from "react-admin";
import { UserList, UserEdit, UserCreate } from './users';
const dataProvider =
jsonServerProvider("https://jsonplaceholder.typicode.com");
class App extends Component {
// Provider store is used to use the store of the redux
// Router is used to define the route and the component to display
render() {
return (
<div>
<Provider store={Store}>
<Router basename="/">
<div>
<Route exact path="/" component={LoginView}>
</Route>
<Route exact path="/register" component={RegisterView}>
</Route>
<Route exact path="/login" component={LoginView}>
</Route>
<Route exact path="/dashboard" component={DashboardView}>
<Route exact path="/admin" component={AdminView}>
<Admin dataProvider={dataProvider}>
<Resource
name="users"
list={UserList}
edit={UserEdit}
create={UserCreate}
/>
</Admin>
</Route>
</div>
</Router>
</Provider>
</div>
);
}
}
export default App;
it displays my react-admin but with my other components (display bug). I would like the react-admin part only in my /admin routes.
For me, the section should only be working in the /admin because i gave this path to my route.
What don't I understand?

react router 4 switch showing two components

I'm trying to split my routes into many files, to achieve this I have a central file called routes.
import React from "react";
import { Router, Route, Switch } from "react-router-dom";
import history from "./History";
import StreamRoutes from "./stream/StreamRoutes";
const Routes = props => {
return (
<React.Fragment>
<Router history={history}>
<Switch>
<Route path="/" exact component={props => <h1>hello world</h1>} />
<StreamRoutes />
</Switch>
</Router>
</React.Fragment>
);
};
export default Routes;
and then a route file for all the main component like so:
import React from "react";
import { Route } from "react-router-dom";
import StreamCreate from "./components/StreamCreate";
import StreamEdit from "./components/StreamEdit";
import StreamList from "./components/StreamList";
import StreamShow from "./components/StreamShow";
const StreamRoutes = props => {
return (
<React.Fragment>
<Route path="/streams" exact component={StreamList} />
<Route path="/streams/new" exact component={StreamCreate} />
<Route path="/streams/:id" exact component={StreamShow} />
<Route path="/streams/edit/:id" exact component={StreamEdit} />
</React.Fragment>
);
};
export default StreamRoutes;
this works except when I try to access "/streams/new" or "/streams/:id", in any of those cases the router show both components at once.
I would like to know how to fix this or a better way to organize my routes would be highly appreciated.
It is possible to use a regex like FuzzyTree suggest, but this can get messy in a bigger project. I would suggest replacing React.Fragment in your StreamRoutes with Switch. This way it works like you'd expect.

Resources