I'm creating a simple react application with 3 user roles. On the login page localhost:3000/login
I have fields for username
and password
. Once those details are entered and the login button is clicked, the data is sent to the backend (running node js) and that data is used to query a MySql database. If the entered data matches a user in the database, the userId
, name
, password
, and role
is sent to the backend. This data is then sent to the front end. I can read the retrieved data from the front end and up to this point it works fine. However, when I'm trying to redirect a user according to the role, say the role is doctor and I want to redirect the user to localhost:3000/doctor
, it goes to localhost:3000/doctor
momentarily and switches to localhost:3000/login?
. Shown below is the code for the login component.
import { useState } from "react";
import Axios from 'axios';
import { useNavigate } from 'react-router-dom'
import './login.css';
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
let navigate = useNavigate()
const handleLogin = () => {
Axios.post("http://localhost:3001/login",
{
email: email,
password: password,
},
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then((response) => {
console.log('response 1', response.data[0]['role'])
if (response.data[0]['role'] === 'doctor') {
navigate('/doctor');
}
});
};
return (
<div>
<form>
<h3>Electronic Prescription System</h3>
<h3>Login</h3>
<label>Email Address</label>
<input
className="inputs"
type="text"
placeholder="email"
onChange={(e) => {
setEmail(e.target.value)
}}
/>
<label>Password</label>
<input
className="inputs"
type="password"
placeholder="password"
onChange={(e) => setPassword(e.target.value)}
/>
<button onClick={handleLogin}>Log in</button>
</form>
</div>
)
};
export default Login;
If I remove all the code inside the handleLogin
function and just have navigate('/doctor');
it redirects properly.
The routes are inside the Main component as shown below.
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Login from "./pages/Login/Login";
import Doctor from "./pages/Doctor/Doctor";
import Patient from "./pages/Patient/Patient";
import Pharmacy from "./pages/Pharmacy/Pharmacy";
const Main = () => {
return (
<Routes>
<Route path="login" element={<Login />} />
<Route path="doctor" element={<Doctor />} />
<Route path="patient" element={<Patient />} />
<Route path="pharmacy" element={<Pharmacy />} />
</Routes>
);
}
export default Main;
The Doctor
Component:
import { HeaderPanel } from '../../components/headerPanel/headerPanel'
import { PrescribePanel } from '../../components/prescribePanel/prescribePanel'
import { PrescriptionsList } from '../../components/prescriptionsList/prescriptionsList'
import './styles.css';
export const Doctor = () => {
return (
<>
<HeaderPanel />
<div className='wrapper'>
<PrescribePanel />
<PrescriptionsList />
</div>
</>
);
}
export default Doctor
I'm using react-router-dom
version 6.6.1 and the react
version is 18.2.0.
Tried using a useEffect
hook to capture the role changing and redirecting, but id did not work either.
CodePudding user response:
What I suspect is happening here is that the "log in" button
is submitting the form which takes the default form action and reloads the page, the current route path being "/login"
. button
elements have a type="submit"
attribute value by default.
To resolve I'd suggest attaching handleLogin
to the form
element's onSubmit
event handler and calling preventDefault
on the onSubmit
event object to prevent submitting the form and prevent reloading the page. This should allow the authentication logic to complete as expected.
Try to get yourself in the habit of being specific with the button
element's type
attribute.
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const handleLogin = (e) => { // <-- onSubmit event object
e.preventDefault(); // <-- don't take form action
Axios.post(
"http://localhost:3001/login",
{ email, password },
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then((response) => {
if (response.data[0]['role'] === 'doctor') {
navigate('/doctor');
}
});
};
return (
<div>
<form onSubmit={handleLogin}> // <-- form onSubmit event handler
<h3>Electronic Prescription System</h3>
<h3>Login</h3>
<label>
Email Address
<input
className="inputs"
type="text"
placeholder="email"
onChange={(e) => setEmail(e.target.value)}
/>
</label>
<label>
Password
<input
className="inputs"
type="password"
placeholder="password"
onChange={(e) => setPassword(e.target.value)}
/>
</label>
<button type="submit"> // <-- be specific with button type
Log in
</button>
</form>
</div>
);
};
export default Login;