ReactJs Problem with displaying home page after user logs-in - javascript

I am using passport.js and jwt token to handle the user authentication state in my react app. After the user logs-in, I store the token in localStorage and so depending on whether there's a token or not in the localStorage, I will updated the isAuthenticated state property.
Now, when a guest user (non-authenticated) user, opens the app, he should not be able to access the home-page of the app.
So I devided the routes that the guest user can access and the authenticated user can access to two different variable guestLinks and authLinks.
And depending on the isAuthenticated property, I will display one of those.
App.js
class App extends Component {
render() {
const authLinks = (
<Switch>
<Route
exact
path="/"
name="Login Page"
render={props => <Login {...props} />}
/>
<Route
exact
path="/404"
name="Page 404"
render={props => <Page404 {...props} />}
/>
<Route
exact
path="/500"
name="Page 500"
render={props => <Page500 {...props} />}
/>
<Route
path="/home"
name="Home"
render={props => <DefaultLayout {...props} />}
/>
</Switch>
);
const guestLinks = (
<Switch>
<Route
exact
path="/"
name="Login Page"
render={props => <Login {...props} />}
/>
<Route
exact
path="/register"
name="Register Page"
render={props => <Register {...props} />}
/>
<Route
exact
path="/404"
name="Page 404"
render={props => <Page404 {...props} />}
/>
<Route
exact
path="/500"
name="Page 500"
render={props => <Page500 {...props} />}
/>
</Switch>
);
const currentState = store.getState();
console.log(
"currentState.auth.isAuthenticated: ",
currentState.auth.isAuthenticated
);
return (
<Provider store={store}>
<HashRouter>
<React.Suspense fallback={loading()}>
{console.log(currentState.auth.isAuthenticated)}
{/* TODO: Not sure if this always works. If after the user logsin he gets a blank page and he has to reload to be redirected to home then
this way of routing may need to modified */}
{currentState.auth.isAuthenticated ? authLinks : guestLinks}
</React.Suspense>
</HashRouter>
</Provider>
);
}
}
Notice this line:
{currentState.auth.isAuthenticated ? authLinks : guestLinks}
So after the user logs in, (so he is authenticated), he is redirected to the home-page:
class Login extends Component {
constructor() {
super();
this.state = {
email: "",
mot_de_passe: "",
errors: ""
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidMount() {
// If the user has already logged-in and he attempts to access the login page this will redirect him to home
if (this.props.auth.isAuthenticated) {
this.props.history.push("/home");
}
}
//This runs when the component receives new properties
componentWillReceiveProps(nextProps) {
// After the user has logged-in this will redirect him to home
if (nextProps.auth.isAuthenticated) {
this.props.history.push("/home");
}
if (nextProps.errors) {
this.setState({ errors: nextProps });
}
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
onSubmit(e) {
console.log(e);
// Since it's a form, we don't want it to have its default behavior
e.preventDefault();
const userInfo = {
email: this.state.email,
password: this.state.mot_de_passe
};
// Any action that we bring-in is going to be stored inside props
//this.props.loginUser(userInfo, this.props.history);
this.props.loginUser(userInfo);
}
render() {
return (
<div className="app flex-row align-items-center">
<Container>
<Row className="justify-content-center">
<Col md="8">
<CardGroup>
<Card className="p-4">
<CardBody>
<Form noValidate onSubmit={this.onSubmit}>
<h1>Se connecter</h1>
<p className="text-muted">
Connectez-vous à votre compte
</p>
<InputGroup className="mb-3">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="icon-user"></i>
</InputGroupText>
</InputGroupAddon>
{/* WORK_HERE */}
<Input
name="email"
type="text"
placeholder="Email"
value={this.state.email}
onChange={this.onChange}
/>
</InputGroup>
<InputGroup className="mb-4">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="icon-lock"></i>
</InputGroupText>
</InputGroupAddon>
<Input
name="mot_de_passe"
type="password"
placeholder="Mot de passe"
autoComplete="current-password"
value={this.state.mot_de_passe}
onChange={this.onChange}
/>
</InputGroup>
<Row>
<Col xs="6">
<Button color="primary" className="px-4">
Se connecter
</Button>
</Col>
<Col xs="6" className="text-right">
<Button color="link" className="px-0">
Mot de passe oubliée?
</Button>
</Col>
</Row>
</Form>
</CardBody>
</Card>
<Card
className="text-white bg-primary py-5 d-md-down-none"
style={{ width: "44%" }}
>
<CardBody className="text-center">
<div>
<h2>Bienvenue au Viwone SAV</h2>
<p>
Suivez en temps réel l'évolution des opérations du
service après-vente.
</p>
</div>
</CardBody>
</Card>
</CardGroup>
</Col>
</Row>
</Container>
</div>
);
}
}
The problem is that after he logs-in, he get a blank screen and he has to reload the page in order for the home-page to be successfully displayed.
It seems that the authLinks don't get loaded fast enough for the app to be able to detect the link to the home screen.

In your App.js, get isAuthenticated value using connect() so it will re-render with latest value of isAuthencticated after login and your will see the updated urls

Related

My edit button adds a new item and my new item link does not work. This is REACT

I'm having issues with React using JSON server, my edit buttons adds a new item when it's supposed to edit the current item and the new item link does not work, it should open a form (the same the edit button opens) and when I hit save it should save to the array the new item. Any ideas please?
I have omitted all the imports to save space. This is App.js
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />}>
<Route index element={<h1>Welcome</h1>} />
<Route path="products" element={<ProductsList />}>
<Route index element={<p>Select a Product for more details</p>}/>
<Route path="new" element={<ProductForm />} />
<Route path=":productId/edit" element={<ProductForm />} />
<Route path=":productId" element={<Product />} />
<Route path="*" element={<h1>Product Not Found</h1>} />
</Route>
</Route>
<Route path="*" element={<h1>Page Not Found</h1>} />
</Routes>
</BrowserRouter>
);
}
export default App;
This is Home.js
function Home() {
return (
<>
<Navbar bg="dark" variant="dark">
<Container>
<Nav className="me-auto">
<Link to="/" className="nav-link">Home</Link>
<Link to="/products" className="nav-link">Products</Link>
<Link to="/newProduct" className="nav-link">New Product</Link>
</Nav>
</Container>
</Navbar>
<Stack gap={3} className="col-md-10 mx-auto mt-3">
<Outlet />
</Stack>
</>
)
}
export default Home
This is ProductForm.js
function ProductForm() {
let [product, setProduct] = useState({
id: "",
productName: "",
description: "",
price: "",
});
let { getProduct, addProduct, updateProduct } = useContext(ProductContext);
let navigate = useNavigate();
let { id, productName, description, price } = product;
useEffect(() => {
if (id === undefined) return;
async function fetch() {
await getProduct(id).then((product) => setProduct(product));
}
fetch();
}, [id]);
function handleChange(event) {
setProduct((preValue) => {
return { ...preValue, [event.target.name]: event.target.value };
});
}
function addOrUpdate() {
if (id === undefined) {
return addProduct(product);
} else {
return updateProduct(product);
}
}
function handleSubmit(event) {
event.preventDefault();
addProduct(product).then((product) => navigate(`/products/${product.id}`));
}
return (
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
name="productName"
value={product.name}
onChange={handleChange}
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Description</Form.Label>
<Form.Control
type="text"
name="description"
value={product.description}
onChange={handleChange}
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Price</Form.Label>
<Form.Control
type="text"
name="price"
value={product.price}
onChange={handleChange}
/>
</Form.Group>
<Form.Group className="mb-3"></Form.Group>
<Button type="submit">Save</Button>
</Form>
);
}
export default ProductForm;
Link to new product should be as route ‘products/new’ unless your redirecting it somewhere
Your handle submit on form always calls addProduct not addOrUpdate

React webpage refreshing every 4-6 seconds

I'm not really sure even what part of my code to show because it's such a general error, but everytime I npm start my React webpage it automatically goes from the home page to the authentication dashboard and starts refreshing.
I'm guessing it's a problem with React Router but I'm not really sure about this either?
This is how my App.js App component currently looks, which has the main Route functionality.
const App = () => {
const [auth, setAuth] = useState(false);
useEffect(() => {
localStorage.setItem("user", auth);
}, [auth]);
return (
<div className="landing" style={{zIndex:0, margin:"0px", position:"fixed"}}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{!auth && (
<Route
path="/auth"
element={
<Auth authenticate={(val) => setAuth(val === 1 ? true : false)} />
}
/>
)}
{auth && (
<>
<Route path="/dashboard" element={<Dashboard />} />
</>
)}
<Route
path="*"
element={<Navigate to={auth ? "/dashboard" : "/auth"} />}
/>
</Routes>
</div>
);
}
And this is how my Home.js Home component file looks like
function Home() {
return (
<div className="main">
<div className="landingImageDiv">
<img src={ligaLogo} alt="uchisvg" className="landingImage" />
<div id="fade" className="linkDiv topMargin5">
<div>
<Link to="/about" className="popupLink">
<span className="hover">[About]</span>
</Link>
</div>
<div>
<Link to="/auth" className="popupLink">
<span className="hover">[Talent Network]</span>
</Link>
</div>
<div>
{/* Format to request access to platform */}
<a href="https://forms.gle/vKzq5M9n56oKKV5DA" className="popupLink">
<span className="hover">[Request RSO Onboarding]</span>
</a>
</div>
</div>
</div>
<div className="landing" id="fade">
<div style={{ zIndex: 5, position: "relative" }}></div>
</div>
</div>
);
}
Change your route definition as follows:
{
!auth ? (
<Route
path="/auth"
element={
<Auth authenticate={(val) => setAuth(val === 1 ? true : false)} />
}
/>
) : (
<>
<Route path="/dashboard" element={<Dashboard />} />
</>
);
}

dispatch inside of child useEffect causes infinite rendering

App.js
return (
<Router history={createBrowserHistory}>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route
path="/login"
element={
<LoginAuth redirectTo="/dashboard">
<SignIn set_token={setAuthToken} setUserType={setUserType} />
</LoginAuth>
}
/>
<Route path="/register" element={<SignUp />} />
<Route
path="/dashboard/*"
element={
<RequireAuth redirectTo="/login">
<UserDashboard />
</RequireAuth>
}
/>
<Route path="/register/subscription" element={<Package />} />
<Route path="/contact" element={<Contact />} />
<Route path="/pricing" element={<Pricing />} />
<Route path="/features" element={<Features />} />
</Routes>
</Router>
);
UserDashboard.js
when route is 'localhost../dashboard' it renders this component and in this useeffect I append URL with home so that home component render automatically.
useEffect(() => {
history("home");
}, []);
return (
<div className="dash-cont background-blue">
<header className="head-cont">
<div className="top-left-head">
<div className="left-header">
<a href="/" className="b-brand">
<span className="logo">SchoolSavvy</span>
</a>
<a href="#!" className="mob-toggler" onClick={onToggle}>
<Hamburger
className="hamburger-react"
toggled={isOpen}
toggle={setOpen}
/>
</a>
<div className="right_head_popup">
<MoreVertIcon />
</div>
</div>
<div className="right-header">
<NotificationsNoneOutlinedIcon className="notify-ico" />
<PersonOutlineOutlinedIcon className="person-ico" />
</div>
</div>
</header>
<div className="body-div">
<UserSidebar is_Open={isOpen} on_Toggle={onToggle} />
<div className="dash-info">
{/* Heading */}
<PathHeading />
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/school/*" element={<SchoolComp />} />
<Route path="/student/*" element={<></>} />
<Route path="/parent/*" element={<></>} />
<Route path="/teacher/*" element={<></>} />
<Route path="/class/*" element={<></>} />
<Route path="/exam/*" element={<></>} />
<Route path="/attendance/*" element={<></>} />
<Route path="/timetable/*" element={<></>} />
</Routes>
</div>
</div>
</div>
);
Home.js
when this component is rendered, dispatch in useEffect causes infinite rendering, anyone knows what's the problem? Thanks
const Home = () => {
const dispatch = useDispatch();
useEffect(() => {
console.log("home rend");
dispatch(loadDashboard());
}, []);
return (
<>
{/* Cards */}
<Card />
<div className="sch_summary">
{/* Charts */}
<BarChart />
<NoticeBoard />
</div>
<Calendar />
</>
);
};
Here is loadDashboard action which is dispatched by useEffect
export const loadDashboard = () => async (dispatch, getstate) => {
try {
dispatch({
type: actionType.DASHBOARD_REQ,
});
console.log(`tokennn: ${getstate().user.token}`);
const { data } = await axios.get("/v1/user/dashboard/detail", {
headers: {
Authorization: `Bearer ${getstate().user.token}`,
},
});
dispatch({
type: actionType.DASHBOARD_SUCCESS,
payload: data.user,
});
} catch (error) {
console.log(`falii: ${error}`);
dispatch({
type: actionType.DASHBOARD_FAILURE,
payload: error.response.data,
});
}
};
One solution is to add the dispatch actions that cause infinite rerender to ref using useRef.
import { useRef } from 'react';
function useAddFnToRef(fn) {
const refProps = useRef({ fn });
return refProps.current.fn;
}
const Home = () => {
const dispatch = useDispatch();
const onLoadDashboard = useAddFnToRef(()=>dispatch(loadDashboard()))
useEffect(() => {
console.log("home rend");
onLoadDashboard();
}, [onLoadDashboard]);
return (
<>
{/* Cards */}
<Card />
<div className="sch_summary">
{/* Charts */}
<BarChart />
<NoticeBoard />
</div>
<Calendar />
</>
);
};

React Update context causes Uncaught Error: Maximum update depth exceeded error

I'm actually building an SPA using React and Symfony and I'm facing an issue with the login part.
react-router-dom 5.2.0
history 4.10.1
I'm trying to redirect the user after successfully logged in to a private route /client but React gives me errors when I try to redirect with history or with the <Redirect />component.
Also, when I redirect to a public route there isn't any error.
I found out that the loop comes from setUser from the AuthContext.
// App.jsx
const App = () => {
const cart = getLocalStorage('cart', []);
const [currentUser, setCurrentUser] = useState(null);
const menu = '';
useEffect(() => {
setCurrentUser(authenticationService.currentUser)
}, [currentUser])
return <AuthProvider value={{ currentUser }}>
<MenuProvider value={{ menu }}>
<CartProvider value={{ cart }}>
<ToastProvider
autoDismiss
autoDismissTimeout={6000}
>
<Router history={history}>
< Navigation />
</Router>
</ToastProvider>
</CartProvider>
</MenuProvider>
</AuthProvider>
};
// Navigation.jsx
export const Navigation = () => {
const [currentUser, setCurrentUser] = useState(null);
const { user, setUser } = useContext(AuthContext)
useEffect(() => {
setCurrentUser(user)
}, [user])
const logout = () => {
authenticationService.logout();
setUser(null)
history.replace('/');
}
return <><div className="header">
<Container>
<Navbar expand="lg" sticky="top">
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="mr-auto">
<NavLink className={"nav-link"} to={"/about"}> A propos </NavLink>
</Nav>
<Nav>
{currentUser && currentUser.username ?
<>
<Link className={"nav-link"} to={"/client"}> Menu </Link>
<NavDropdown title="Compte" id="collasible-nav-dropdown">
<NavDropdown.Item to={"/profile"} as={Link}>
Profile
</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item onClick={logout} to={"/logout"}> Déconnexion </NavDropdown.Item>
</NavDropdown>
</>
:
<NavLink className={"nav-link"} to={"/login"}> Connexion </NavLink>
}
</Nav>
</Navbar.Collapse>
</Navbar >
</Container>
</div>
<Switch>
<Route exact path="/" component={withRouter(Home)} />
<Route exact path="/home" component={Home} />
<Route exact path="/about" component={About} />
<Route exact path="/logout" />
<Route exact path="/login" component={LoginPage} />
<Route exact path="/register" component={RegisterPage} />
<Redirect from="/logout" to="/home" />
<PrivateRoute exact path="/client" component={Client} />
</Switch>
</>
}
// LoginPage.jsx
const LoginPage = () => {
const [values] = useState(initialValues);
const [isLoading, setIsLoading] = useState(false);
const [redirect, setRedirect] = useState(false);
const { user, setUser } = useContext(AuthContext);
const { register, handleSubmit, formState: { errors }, reset } = useForm({ mode: 'all' });
const { addToast } = useToasts();
const { from } = { from: { pathname: "/client" } };
const onSubmit = async data => {
setRedirect(true);
setIsLoading(true);
await authenticationService.login(data);
setUser(await authenticationService.currentUser.username);
addToast(`Welcome back ${data.username} !`, {
appearance: 'success',
autoDismiss: true,
})
setIsLoading(false);
history.push(from);
reset();
}
return user ?
<Redirect to="/client" />
: (<Container>
<div className="row">
<div className="col-lg-8 mx-auto">
<Card>
<Card.Header>
<Row style={{ justifyContent: 'center' }}>
<Card.Title
style={{ marginTop: 'auto', marginBottom: 'auto' }}>
— Connexion
</Card.Title>
</Row>
</Card.Header>
<Card.Body>
<Form noValidate onSubmit={handleSubmit(onSubmit)}>
<Form.Group>
<Form.Row>
<Col md="5" style={{ textAlign: 'end', marginTop: 'auto', marginBottom: 'auto' }}>
<Form.Label
required
className="bold">
Code utilisateur
</Form.Label>
<FontAwesomeIcon icon={faEdit} />
</Col>
<Col md="6">
<Form.Control
{...register("username",
{
required: true
})}
type="text"
id="username"
defaultValue={values.username}
placeholder="Saisissez votre code utilisateur" />
</Col>
</Form.Row>
</Form.Group>
<Form.Group>
<Form.Row>
<Col md="5" style={{ textAlign: 'end', marginTop: 'auto', marginBottom: 'auto' }}>
<Form.Label
required
className="bold">
Mot de passe
</Form.Label>
<FontAwesomeIcon icon={faLock} />
</Col>
<Col md="6">
<Form.Control
{...register("password",
{
required: true,
minLength: 6,
// pattern: /[A-Za-z]{3}/,
})}
type="password"
id="password"
placeholder="Saisissez votre mot de passe" />
</Col>
</Form.Row>
</Form.Group>
<Card.Footer className="text-center">
{
isLoading ? (
<Button type="submit" className="btn-sample" disabled={isLoading}>
<span className="fa-1x">
<i className="fas fa-circle-notch fa-spin"></i>
</span>
<span style={{ padding: '0.5em' }}>Connexion</span>
<FontAwesomeIcon icon={faUser} />
</Button>
) : (
<Button type="submit" className="btn-sample">
<span style={{ padding: '1em' }}>Connexion</span>
<FontAwesomeIcon icon={faUser} />
</Button>
)
}
</Card.Footer>
</Form>
</Card.Body>
</Card>
</div>
</div>
</Container>)
}
The errors:
Uncaught (in promise) Error: Maximum update depth exceeded. This can
happen when a component repeatedly calls setState inside
componentWillUpdate or componentDidUpdate. React limits the number of
nested updates to prevent infinite loops.
Uncaught Error: Maximum update depth exceeded. This can happen when a
component repeatedly calls setState inside componentWillUpdate or
componentDidUpdate. React limits the number of nested updates to
prevent infinite loops.
Warning: Can't perform a React state update on an 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
cleanup function
Any idea ?
Thank you so much ^^
You don't have to pass currentUser to the dependencies array. You can pass either empty array or [authenticationService.currentUser]

React Router Link is Showing Two Components

I didn't know the best way to describe this issue, but I'm going to try and explain as best I can.
In my core React App component, i'm doing a conditional render, based on if a user is logged in.
If Logged In --- I show the main page, and if not, they get the login screen.
On my login page, i'm trying to put in a link at the bottom which directs a user to signup for a new account. My issue that when I click to this 'newuser' page, it is rendering both my login form and the create user form, both different components (see below).
I suspect this is an issue with how I have my react router setup, but I'm not sure what the problem is.
Here is the code in my App component.
<Container>
<Router>
<Notification />
{props.loggedUser ? (
<div>
<Navbar />
<Route exact path="/" render={() => <Blogs />} />
<Route exact path="/blogs" render={() => <Blogs />} />
<Route path="/login" render={() => <Login />} />
<Route
exact
path="/blogs/:id"
render={({ match }) => (
<Blog
blog={blogById(match.params.id)}
user={props.loggedUser}
/>
)}
/>
<Route exact path="/users" render={() => <Users />} />
<Route
exact
path="/users/:id"
render={({ match }) => <User user={userById(match.params.id)} />}
/>
</div>
) : (
<>
<Login />
</>
)}
</Router>
<div>
<br />
<em>Blog app, John 2019</em>
</div>
</Container>
And here is my Login component. I've tried including the route for the new users page on both sides of the conditional statement above and then also in the Login Form below, as I have now. All are leading to the same issue.
<h1>Login To Blog Application</h1>
<Form onSubmit={handleLogin}>
<Form.Field>
<label>username</label>
<input {...username.omitreset} name="username" />
</Form.Field>
<Form.Field>
<label>password</label>
<input {...password.omitreset} type="password" />
</Form.Field>
<Button type="submit">login</Button>
<div>
<br />
<Link to="/newuser">or signup to become a new user</Link>
<Route path="/newuser" render={() => <NewUser />} />
</div>
</Form>
</>
and NewUser component
import React from "react";
import { connect } from "react-redux";
import { createUser } from "../reducers/userReducer";
import { setNotification } from "../reducers/notificationReducer";
import { Form, Button } from "semantic-ui-react";
const NewUser = props => {
const addUser = event => {
event.preventDefault();
const userObject = {
username: event.target.username.value,
name: event.target.name.value,
password: event.target.password.value
};
event.target.username.value = "";
event.target.name.value = "";
event.target.password.value = "";
props.createUser(userObject);
};
return (
<>
<h1>Create a New Blog Account</h1>
<Form onSubmit={addUser}>
<Form.Field>
<label>username</label>
<input {...props.username} name="username" />
</Form.Field>
<Form.Field>
<label>name</label>
<input {...props.name} type="password" />
</Form.Field>
<Form.Field>
<label>password</label>
<input {...props.password} type="password" />
</Form.Field>
<Button type="submit">login</Button>
</Form>
</>
);
};
const mapDispatchToProps = {
createUser,
setNotification
};
export default connect(null, mapDispatchToProps)(NewUser);
you shouldn't do conditional rendering, because when the user is not logged the Loggin component is rendered and is not depended on the path at all. then you change the path by clicking Link to="/newuser" and the Sign up renders inside
I got this working based on det2dachoppa's recommendations. Removed the conditional and added the Switch and redirects to ensure that a user can't view the pages without logging in.
<Router>
<Notification />
<div>
<Navbar />
<Switch>
{props.loggedUser && (
<React.Fragment>
<Route exact path="/">
<Blogs />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/blogs">
<Blogs />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route
exact
path="/blogs/:id"
render={({ match }) => (
<Blog
blog={blogById(match.params.id)}
user={props.loggedUser}
history={props.history}
/>
)}
/>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/users">
<Users />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route
exact
path="/users:id "
render={({ match }) => (
<User user={userById(match.params.id)} />
)}
/>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/newblog">
<NewBlog />
</Route>
</React.Fragment>
)}
<Route path="/login">
<Login />
</Route>
<Route path="/newuser">
<NewUser />
</Route>
<Redirect to="/login">
<Login />
</Redirect>
</Switch>
</div>
</Router>

Categories

Resources