I am running a Django Rest backend with a React front-end.
JSON data during user registration is being pushed per normal. When users submit the register form, they are sent to a login page. I realize how annoying this is for the users, however I’m not so sure how automatically send the user to the logged-in version of the homepage.
I would like to accomplish this in the frontend (I have multiple ways to verify, thanks to social logins, so just seems easier to code this once in the front-end for all methods of registration)
register.js post
you can see below I push the user to /login
, however I just want to push them to /home
in an already verified and authorized state.
const handleSubmit = (e) => { e.preventDefault(); console.log(formData); axiosInstance .post(`user/register/`, { email: formData.email, username: formData.username, first_name: formData.first_name, last_name: formData.last_name, password: formData.password, subscribed: formData.subscribed, }) .then((res) => { history.push('/login'); console.log(res); console.log(res.data); }); };
I have access_tokens
and refresh_tokens
generated by Django, which I can access thanks to my axios instances.
my main axios.js
import axios from 'axios'; const baseURL = 'http://127.0.0.1:8000/api/'; const axiosInstance = axios.create({ baseURL: baseURL, timeout: 5000, headers: { Authorization: 'Bearer ' + localStorage.getItem('access_token'), 'Content-Type': 'application/json', accept: 'application/json', }, }); axiosInstance.interceptors.response.use( (response) => { return response; }, async function (error) { const originalRequest = error.config; if (typeof error.response === 'undefined') { alert( 'A server/network error occurred. ' + 'Looks like CORS might be the problem. ' + 'Sorry about this - we will get it fixed shortly.' ); return Promise.reject(error); } if ( error.response.status === 401 && originalRequest.url === baseURL + 'token/refresh/' ) { window.location.href = '/login/'; return Promise.reject(error); } if ( error.response.data.code === 'token_not_valid' && error.response.status === 401 && error.response.statusText === 'Unauthorized' ) { const refreshToken = localStorage.getItem('refresh_token'); if (refreshToken) { const tokenParts = JSON.parse(atob(refreshToken.split('.')[1])); // exp date in token is expressed in seconds, while now() returns milliseconds: const now = Math.ceil(Date.now() / 1000); console.log(tokenParts.exp); if (tokenParts.exp > now) { return axiosInstance .post('/token/refresh/', { refresh: refreshToken, }) .then((response) => { localStorage.setItem('access_token', response.data.access); localStorage.setItem('refresh_token', response.data.refresh); axiosInstance.defaults.headers['Authorization'] = 'JWT ' + response.data.access; originalRequest.headers['Authorization'] = 'JWT ' + response.data.access; return axiosInstance(originalRequest); }) .catch((err) => { console.log(err); }); } else { console.log('Refresh token is expired', tokenParts.exp, now); window.location.href = '/login/'; } } else { console.log('Refresh token not available.'); window.location.href = '/login/'; } } // specific error handling done elsewhere return Promise.reject(error); } ); export default axiosInstance;
I think I can copy some code from my login.js
file to get users tokens directly?
login.js
import React, { useState } from 'react'; import axiosInstance from '../../axios/Login'; import { useHistory } from 'react-router-dom'; import FbLogin from 'react-facebook-login'; import FacebookLogin from '../../axios/facebookLogin'; //MaterialUI import Avatar from '@material-ui/core/Avatar'; import Button from '@material-ui/core/Button'; import CssBaseline from '@material-ui/core/CssBaseline'; import TextField from '@material-ui/core/TextField'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Checkbox from '@material-ui/core/Checkbox'; import Link from '@material-ui/core/Link'; import Grid from '@material-ui/core/Grid'; import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import Container from '@material-ui/core/Container'; const useStyles = makeStyles((theme) => ({ paper: { marginTop: theme.spacing(8), display: 'flex', flexDirection: 'column', alignItems: 'center', }, avatar: { margin: theme.spacing(1), backgroundColor: theme.palette.secondary.main, }, form: { width: '100%', // Fix IE 11 issue. marginTop: theme.spacing(1), }, submit: { margin: theme.spacing(3, 0, 2), }, })); export default function SignIn() { const history = useHistory(); const initialFormData = Object.freeze({ email: '', password: '', }); const [formData, updateFormData] = useState(initialFormData); const handleChange = (e) => { updateFormData({ ...formData, [e.target.name]: e.target.value.trim(), }); }; const handleSubmit = (e) => { e.preventDefault(); console.log(formData); axiosInstance .post(`auth/token/`, { grant_type: 'password', username: formData.email, password: formData.password, client_id: 'xxx', client_secret: 'xxx', }) .then((res) => { console.log(res); localStorage.setItem('access_token', res.data.access_token); localStorage.setItem('refresh_token', res.data.refresh_token); history.push('/'); window.location.reload(); }); }; const responseFacebook = async (response) => { FacebookLogin(response.accessToken); }; const classes = useStyles(); return ( <Container component="main" maxWidth="xs"> <CssBaseline /> <div className={classes.paper}> <Avatar className={classes.avatar}></Avatar> <Typography component="h1" variant="h5"> Sign in </Typography> <form className={classes.form} noValidate> <TextField variant="outlined" margin="normal" required fullWidth id="email" label="Email Address" name="email" autoComplete="email" autoFocus onChange={handleChange} /> <TextField variant="outlined" margin="normal" required fullWidth name="password" label="Password" type="password" id="password" autoComplete="current-password" onChange={handleChange} /> <FormControlLabel control={<Checkbox value="remember" color="primary" />} label="Remember me" /> <Button type="submit" fullWidth variant="contained" color="primary" className={classes.submit} onClick={handleSubmit} > Sign In </Button> <FbLogin appId="719891865332276" fields="name,email" //picture callback={responseFacebook} /> <Grid container> <Grid item xs> <Link href="#" variant="body2"> Forgot password? </Link> </Grid> <Grid item> <Link href="#" variant="body2"> {"Don't have an account? Sign Up"} </Link> </Grid> </Grid> </form> </div> </Container> ); }
Sorry if things seem a little obscure, I’m new to react, I appreciate any type of assistance.
Advertisement
Answer
First, You need to manage states of users (logged in or not). So you can use [Redux][1] for manage states of users.
Next thing is redirect users to /home page. React in default only support single page web applications. So you can’t use window.location.href
.You need to use [React-Router][2] for do that.
If you need example, see:: https://github.com/krypto-i9/fixbit/tree/main/src. (this repo use redux to manage user states and react-router for route between pages)
[1]: https://redux.js.org/introduction/getting-started
[2]: https://reactrouter.com/web/guides/quick-start