This is code for looping through routes file. Here i am creating routerconfig array an exporting from here to app.js.
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import routes from './routes';
class RouterConfig extends Component {
render() {
return (
routes.map((route) => {
return (
<Route
key={ route.id }
path={ route.path }
exact={ route.exact }
component={ route.component }
/>
);
})
);
}
}
export default RouterConfig;
This is my route configuration file, where i have listed all routes.
import Home from '../components/home/home';
import About from '../components/about/about';
import Posts from '../components/posts/posts';
import NotFound from '../components/not_found/not_found';
const routes = [
{
path: '/',
exact: true,
component: Home,
id: 'home',
},
{
path: '/about',
component: About,
id: 'about',
},
{
path: '/posts',
component: Posts,
id: 'posts',
},
{
component: NotFound,
id: 'not_found',
},
];
export default routes;
This is my app.js
import React, { Component } from 'react';
import { Switch, Router, Route } from 'react-router-dom';
import Header from '../header/header';
import Footer from '../footer/footer';
import history from '../../history';
import RouterConfig from '../../router/browserroute';
class App extends Component {
render() {
return (
<div>
<Router history={ history } >
<div>
<Header />
<Switch>
<RouterConfig />
</Switch>
<Footer />
</div>
</Router>
</div>
);
}
}
export default App;
issue is on every page i am getting not found component render. Even
using switch with routes not getting the expected results. not sure
why code is not working properly.
[this is how it renders not found in every page ][1]
[1]: https://i.stack.imgur.com/B7evW.png
on changing:
class App extends Component {
render() {
return (
<div>
<Router history={ history } >
<div>
<Header />
<Switch>
<Route exact path='/' component={ Home } />
<Route path='/about' component={ About } />
<Route path='/posts' component={ Posts } />
<Route component={ NotFound } />
</Switch>
<Footer />
</div>
</Router>
</div>
);
}
}
This works fine
You need to move Switch to be inside RouteConfig. There must be something with the way React 16 partials work that is unexpected in React Router (I'm not really sure why it does not work when Switch is outside RouterConfig). The good news is, at least for me, it makes sense to be inside RouteConfig.
Here is a codesandbox that works:
https://codesandbox.io/s/8xmx478kq8
Which version of React are you using? If you are using React 15 or lower, it does not support returning an array inside render. You would need to wrap you stuff in a container.
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import routes from './routes';
class RouterConfig extends Component {
render() {
return (
<div>{
routes.map((route) => {
return (
<Route
key={ route.id }
path={ route.path }
exact={ route.exact }
component={ route.component }
/>
);
})
}</div>
);
}
}
export default RouterConfig;
Notice the div wrapping the Routes array
Related
The issue is that whenever I try to migrate my routes into another file and import them into parent file(routes.js) then whenever I tried to navigate to those migrated route the whole layout is re-rendered and if I keep migrated routes in the parent route component then the layout is rendered once as expected.
The route component where all the routes are written as below
routes.js
import React, { Component } from 'react';
import {Route, Switch} from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import MainLayout from '../pages/layouts/MainLayout';
import Login from '../components/Login/Login';
import UserList from "../components/User/UserList";
import UserCreate from '../components/User/UserCreate';
import UserEdit from '../components/User/UserEdit';
import UserSetting from '../components/User/UserSetting';
class Main extends Component {
render() {
return (
<Switch>
<Route exact path='/' component={Login}/>
<PrivateRoute exact path='/user' component={UserList} layout={MainLayout}/>
<PrivateRoute exact path='/user/create' component={UserCreate} layout={MainLayout}/>
<PrivateRoute exact path='/user/edit/:id' component={UserEdit} layout={MainLayout}/>
<PrivateRoute exact path='/user/setting/:id' component={UserSetting} layout={MainLayout}/>
</Switch>
)
}
}
export default Main;
UserRoutes.js
import UserList from "../components/User/UserList";
import UserCreate from '../components/User/UserCreate';
import UserEdit from '../components/User/UserEdit';
import UserSetting from '../components/User/UserSetting';
const UserRoutes = [
{
path : '/user',
component : UserList,
},
{
path : '/user/create',
component : UserCreate,
},
{
path : '/user/edit/:id',
component : UserEdit,
},
{
path : '/user/setting/:id',
component : UserSetting,
},
];
export default UserRoutes;
Now, when I try to import this route in place of the written routes in routes.js component, the above mentioned issue arises.
routes.js
import React, { Component } from 'react';
import {Route, Switch} from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import MainLayout from '../pages/layouts/MainLayout';
import Login from '../components/Login/Login';
import UserRoutes from './UserRoutes';
class Main extends Component {
render() {
return (
<Switch>
<Route exact path='/' component={Login}/>
{
UserRoutes.map(({ path, component }, key) =>
<PrivateRoute exact layout={MainLayout} path={path} component={component} key={key} />
)
}
</Switch>
)
}
}
export default Main;
PrivateRoute.js
import React from 'react';
import {Redirect, Route, withRouter} from 'react-router-dom';
let state_of_state = localStorage["appState"];
let Auth = {};
if (!state_of_state){
localStorage["appState"] = JSON.stringify({user : {}});
} else {
Auth = JSON.parse(state_of_state);
}
const PrivateRoute = ({ layout: Layout, component: Component, ...rest }) => (
<Route {...rest} render={props => {
const newComponent = Layout ?
<Layout><Component {...rest} {...props} /></Layout>
:
<Component {...props} />;
return (!_.isEmpty(Auth.user)) ? (
newComponent
) : (
<Redirect to={{pathname: '/', state: { from: props.location }}} />
)
}}/>
);
export default PrivateRoute;
I need some guidance where I am going wrong with this.
I have a react web app with a sidemenu. Whenever a user clicks on the link in the sidemenu, they are routed to a page that is rendered at the right side of the sidemenu. My question is, how do I do login for such a usecase seeing as any page I route to renders to the right of the sidemenu. I want the login page to be full screen without the side menu showing. This is what App.js looks like.
import React, { Component } from "react";
import { HashRouter } from "react-router-dom";
import Navigation from "./pages/General/components/Navigation";
import SideMenu from "./pages/General/components/SideMenu";
import "../src/css/App.css";
class App extends Component {
render() {
return (
<div>
<HashRouter>
<div className="main-wrapper">
<SideMenu />
<Navigation />
</div>
</HashRouter>
</div>
);
}
}
export default App;
Here is Navigation.js
import React from "react";
import { Route } from "react-router-dom";
import CalendarPage from "../../Calendar/CalendarPage";
import DoctorsList from "../../Doctors/DoctorsList";
import PatientsList from "../../Patients/PatientsList";
import AdminUsersList from "../../AdminUsers/AdminUsersList";
import SpecialitiesList from "../../Specialities/SpecialitiesList";
const Navigation = () => {
return (
<div className="mainarea">
<Route exact path="/" component={CalendarPage} />
<Route exact path="/scheduler" component={CalendarPage} />
<Route exact path="/doctors" component={DoctorsList} />
<Route exact path="/patients" component={PatientsList} />
<Route exact path="/admin-users" component={AdminUsersList} />
<Route exact path="/specialities" component={SpecialitiesList} />
</div>
);
};
export default Navigation;
The best solution I can figure out in terms of a clean design, is to implement another router in your App.jsx, because you are implementing the routing inside your component, and you need another one for your login page.
Then, your App.jsx could be like this:
import React, { Component } from "react";
import { Redirect, Route, Switch } from "react-router-dom";
import LogIn from "./pages/General/components/Login";
import HomePage from "./pages/General/components/HomePage";
import "../src/css/App.css";
class App extends Component {
render() {
return (
<div>
<Switch>
<Route path={'/login'} component={LogIn} />
<Route path={'/'} component={HomePage} />
<Redirect to="/" />
</Switch>
</div>
);
}
}
export default App;
Then, for your HomePage do the following
import React, { Component } from "react";
import { HashRouter } from "react-router-dom";
import Navigation from "./pages/General/components/Navigation";
import SideMenu from "./pages/General/components/SideMenu";
import "../src/css/App.css";
class HomePage extends Component {
render() {
return (
<div>
<HashRouter>
<div className="main-wrapper">
<SideMenu />
<Navigation />
</div>
</HashRouter>
</div>
);
}
}
export default HomePage;
I hope it helps!
Here is my solution, it not exactly a solution, but it will give you a basic idea on how to implement this.
The idea is to place the Login component in app.js, and conditionally display it if the user is logged in.
You will have to pass a handler function to login component through which you will be able to control app.js state.
When login will be sucessfull, u can show the Navigation and Sidemenu component.
import { Fragment } from "react";
import Login from "path/to/login";
class App extends Component {
state = { isLoggedIn: false };
loginHandler = () => {
this.setState({
isLoggedIn: true
});
};
render() {
return (
<div>
<div className="main-wrapper">
{isLoggedIn ? (
<Fragment>
<SideMenu />
<Navigation />
</Fragment>
) : (
<Login loginHandler={this.loginHandler} />
)}
</div>
</div>
);
}
}
Also you need write a separate router file, which will contain the main app.
This is used to show the app component when navigated to /
import React from 'react';
import { HashRouter, Route } from 'react-router-dom';
import App from './app';
const MainRoute = () => (
<HashRouter>
<Route path="/" component={App} />
</HashRouter>
);
export default MainRoute;
I am putting together a small application to get used to React, now I have installed React-Router-Dom and when I click a link the URL correctly changes. The issue is that the correct Component does not display.
index.js
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
registerServiceWorker();
App.js
import React, { Component } from 'react';
import Sidebar from './Components/Sidebar';
import SidebarItem from './Components/SidebarItem';
import Home from './Components/Home';
import './App.scss';
import { Link, Route, Switch } from 'react-router-dom';
class App extends Component {
constructor() {
super();
this.state = {};
}
render() {
return (
<div className="App">
<Link to='/home'>Home</Link>
<Switch>
<Route path='/home' Component={Home} />
</Switch>
</div>
);
}
}
export default App;
Can anyone tell me the reason why HomeComponent does not appear?
The prop of the Route that takes a component is spelled component with a small c, not Component.
Example
function Home() {
return <div> Home </div>;
}
class App extends Component {
render() {
return (
<Router>
<div>
<Link to="/home">Home</Link>
<Switch>
<Route path="/home" component={Home} />
</Switch>
</div>
</Router>
);
}
}
EDIT : I found the solution, I forget switch component in my routes.js
I have created a route like that : /post/:id
my routes.js look like :
import React, { Component } from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Posts from "./components/Posts";
import Post from "./components/Post";
class Routes extends Component {
render() {
return (
<div>
<BrowserRouter>
<div>
<Route exact path="/" component={Posts} />
<Route path="/post/:id" component={Post} />
</div>
</BrowserRouter>
</div>
);
}
}
export default Routes;
At my /route I listed all my posts, and when I click on one of them I update the url http://localhost:3000/post/1 for example.
PS : I tried to use withRouter function as it says in the official document of react-router, but this case not work in my case.
The file in question is post.js it look like :
import React, { Component } from "react";
import { active_post } from "../actions/index";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
class Post extends Component {
componentWillMount() {
this.props.active_post(this.props.match.params.id);
}
render() {
console.log(this.props.post);
return (
<div>
<h1>Detail d'un post</h1>
<p>{this.props.match.params.id}</p>
</div>
);
}
}
function mapStateToProps(state) {
return {
post: state.activePost
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ active_post }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Post);
So for example, if I enter manually in the URL bar http://localhost:3000/post/3 for example I have the component and the console.log() with the post when I need.
So please if you have a solution for this case I take this.
Thanks you :)
You should try adding a Switch from react-router-dom around your routes.
<BrowserRouter>
<div>
<Switch>
<Route exact path="/" component={Posts} />
<Route path="/post/:id" component={Post} />
</Switch>
</div>
</BrowserRouter>
Don't forget to include the Switch module from react-router-dom in your component.
import { Route, Switch } from 'react-router-dom';
I'm trying to redirect the user to the login page when the /logout routes is hit. The auth is working (jwt token is removed, but the app fails to redirect to /login.
Also If I do to / the app crashes as well.
On the Login route I uses withRouter from the react-router-dom package wih this I can access the this.props.history.push('/redirect_to_a_new_path'), but when I try to wrap the App component with withRouter method it crashes as well.
Please help!
Here is the github repo:
App.js
import React, { Component } from "react";
import {
BrowserRouter as Router,
Route,
Switch,
withRouter
} from "react-router-dom";
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
import lightBaseTheme from "material-ui/styles/baseThemes/lightBaseTheme";
import getMuiTheme from "material-ui/styles/getMuiTheme";
import injectTapEventPlugin from "react-tap-event-plugin";
// Components
import Navbar from "./components/Navbar";
import HomePage from "./components/HomePage";
import SpotMap from "./components/SpotMap";
import SignUpPage from "./components/containers/SignUpPage";
import LoginPage from "./components/containers/LoginPage";
import DashboardPage from "./components/containers/DashBoardPage";
import NotFound from "./components/NoteFound";
import Auth from "./modules/Auth";
import "./styles/App.css";
injectTapEventPlugin();
const handleLogout = event => {
Auth.deauthenticateUser();
this.props.history.push("/login");
};
const isLoggedIn = event => {
if (Auth.isUserAuthenticated()) {
this.props.history.push(DashboardPage);
} else {
this.props.history.push(HomePage);
}
};
class App extends Component {
render() {
return (
<MuiThemeProvider muiTheme={getMuiTheme(lightBaseTheme)}>
<Router>
<div>
<Navbar />
<Switch>
<Route exact path="/" component={isLoggedIn} />
<Route path="/spotmap" component={SpotMap} />
<Route path="/dashboard" component={DashboardPage} />
<Route path="/signup" component={SignUpPage} />
<Route path="/login" component={LoginPage} />
<Route path="/logout" component={handleLogout} />
<Route component={NotFound} />
</Switch>
</div>
</Router>
</MuiThemeProvider>
);
}
}
export default App;
This is written in React Router v3 and this is what I need to convert to React Router V4. The routes that does not work for me are the "/" and "logout" routes.
import Base from './components/Base.jsx';
import HomePage from './components/HomePage.jsx';
import DashboardPage from './containers/DashboardPage.jsx';
import LoginPage from './containers/LoginPage.jsx';
import SignUpPage from './containers/SignUpPage.jsx';
import Auth from './modules/Auth';
const routes = {
// base component (wrapper for the whole application).
component: Base,
childRoutes: [
{
path: '/',
getComponent: (location, callback) => {
if (Auth.isUserAuthenticated()) {
callback(null, DashboardPage);
} else {
callback(null, HomePage);
}
}
},
{
path: '/login',
component: LoginPage
},
{
path: '/signup',
component: SignUpPage
},
{
path: '/logout',
onEnter: (nextState, replace) => {
Auth.deauthenticateUser();
// change the current URL to /
replace('/');
}
}
]
};
export default routes;
For the / route you should use render like this:
<Route exact path="/" render={() => {
if (Auth.isUserAuthenticated()) {
(<DashboardPage)/>)
} else {
(<HomePage/>)
}
}} />
For your /logout route using <Redirect>
<Route path="/logout" render={() => {
Auth.deauthenticateUser();
return <Redirect to={{ pathname: "/login" }} />;
}}
/>
I post a second solution for the /logout path using withRouter and this.props.history.push('/login').
Point the /logout Route to its own component "Logout"
wrap the Logout component with withRouter method from react-router-dom.
Logout.js
import React, { Component } from "react";
import Auth from "../modules/Auth";
import { withRouter } from "react-router-dom";
class Logout extends Component {
constructor(props) {
super(props);
this.handleLogout = this.handleLogout.bind(this);
}
handleLogout() {
Auth.deauthenticateUser();
this.props.history.push("/login");
}
render() {
return (
<div>
{this.handleLogout()}
</div>
);
}
}
export default withRouter(Logout);
I would use useHistory.
Do:
import { useHistory } from 'react-router-dom';
Instead of:
import { useHistory } from 'react-router';
(Or else the same error message will appear.)