I'm using dj-rest-auth for the authentication endpoints in my django project and reactjs in the frontend of my project. What happens if after I login, the user can still go to the /login
page which should not.
Here's my LoginForm
code:
import React, { useState } from 'react';
import { Form, Button, Alert, Container } from 'react-bootstrap';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
const LoginForm = () => {
const navigate = useNavigate();
const [credentials, setCredentials] = useState({ username: '', password: '' });
const [error, setError] = useState(null);
const handleChange = (e) => {
const { name, value } = e.target;
setCredentials((prevCredentials) => ({ ...prevCredentials, [name]: value }));
};
const validateCredentials = () => {
if (credentials.username.length < 4) {
setError('Username must be longer than 4 characters.');
return false;
}
if (credentials.password.length < 8) {
setError('Password must be at least 8 characters.');
return false;
}
return true;
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!validateCredentials()) {
return;
}
try {
const response = await axios.post('http://localhost:8000/api-auth/login/', credentials);
const token = response.data.token;
localStorage.setItem('token', token);
navigate('/rants');
} catch (error) {
handleLoginError(error);
}
};
const handleLoginError = (error) => {
console.log(error.response);
if (error.response && error.response.status === 400) {
const errorMessage = error.response.data.non_field_errors
? error.response.data.non_field_errors[0]
: 'An error occurred while processing your request. Please try again later.';
setError(errorMessage);
} else {
setError('An unexpected error occurred. Please try again later.');
}
};
return (
<Container className="mt-5">
<h2>Login</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3" controlId="formUsername">
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
placeholder="Enter username"
name="username"
value={credentials.username}
onChange={handleChange}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Enter password"
name="password"
value={credentials.password}
onChange={handleChange}
/>
</Form.Group>
<Button variant="primary" type="submit">
Login
</Button>
</Form>
</Container>
);
};
export default LoginForm;
My AuthContext
// AuthContext.js
import { createContext, useContext, useState } from 'react';
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [token, setToken] = useState(localStorage.getItem('token') || null);
const login = (newToken) => {
setToken(newToken);
localStorage.setItem('token', newToken);
};
const logout = () => {
setToken(null);
localStorage.removeItem('token');
};
return (
<AuthContext.Provider value={{ token, login, logout }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);
What else am I missing here?
You can make something like this in your routing folder if you are using react-router-dom
This will allow you to have two different route paths one private and one public. If token exists in provider state then private routes will be accessed by the user.