Home > Enterprise >  Handle response in React with Axios
Handle response in React with Axios

Time:04-27

In my company I am developing a React application starting from the project base used by the company. In the app we manage the user login by calling an API that responds with an access_token, and it work well. The access_token must therefore be saved on the browser's local storage. I then configured the API and I make the authentication API request, and it answers me correctly with the authentication token, but it is not saved on the browser's local storage.

Do you have any suggestions or advice? Did I do something wrong or do I need to change the basic template of the project?

MyCode:

  • auth.js
import api from "../api/axios";
import jwt_decode from "jwt-decode";
// Set all future requests to use the token.
const setToken = () => {
  const token = localStorage.getItem("token");
  if (token) {
    api.interceptors.request.use(
      async (config) => {
        config.headers = {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
          useCredentials: true,
        };
        return config;
      },
      (error) => {
        Promise.reject(error);
      }
    );
  }
};

// Get new Token by API CALL.
const tokenAPICALL = async (user, pass) => {
  if (user && pass) {
    const { data } = await api.post(
      `/login`,
      {
        email: user,
        password: pass,
      },
      {
        method: 'POST',
        headers: {
          "Content-Type": "application/json; charset=UTF-8",
        },
      }
    ).then((response) => {
       console.log(response);
    }, (error) => {
      console.log(error);
    });

    const jwt_Token_decoded = jwt_decode(data.data.access_token);

    const expiryDate = jwt_Token_decoded.exp;
    if (jwt_Token_decoded.exp * 1000 > Date.now()) {
      localStorage.setItem("token", data.data.access_token);
      localStorage.setItem("token_exp", expiryDate);
    } else {
      console.log("failed token");
    }
    return data.data.access_token;
  }
  return null;
};

// Check the Token stored in Cookies.
const getToken = async (user, pass) => {
  const storedJwt = localStorage.getItem("token");
  const expiration = localStorage.getItem("token_exp");
  if (expiration && storedJwt) {
    if (expiration * 1000 > Date.now()) {
      console.log("Keep Token");
      setToken();
    } else {
      console.log("Expired Token");
      return await tokenAPICALL(user, pass);
    }
  } else {
    // No token recorder in session, Get new token
    console.log("No Token");
    return await tokenAPICALL(user, pass);
  }
};

export default getToken;


  • EDIT: (More code to clarify) LoginForm.js
import React, { useState } from "react";
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 Box from '@material-ui/core/Box';
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import history from './../../history';
import getToken from "../../auth/auth";

function Copyright() {
  return (
    <Typography variant="body2" color="textSecondary" align="center">
      {'Copyright © '}
      <Link color="inherit" href="https://material-ui.com/">
        Your Website
      </Link>{' '}
      {new Date().getFullYear()}
      {'.'}
    </Typography>
  );
}

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 LoginPage() {
    const classes = useStyles();
    const [alertState, setAlertstate] = useState({
        open: false,
        vertical: "bottom",
        horizontal: "center",
        severity: "success",
        message: "",
    });
    const { vertical, horizontal, open, severity, message } = alertState;
    const [loginObj, setLoginObj] = useState({ username: "", password: "" });

    const handleSubmit = async (e) => {
        try {
            localStorage.clear();
            var jwtres = await getToken(loginObj.username, loginObj.password);

            if (jwtres) {
                setAlertstate({
                    open: true,
                    vertical: "bottom",
                    horizontal: "center",
                    message: "Login Successfully.",
                    severity: "success",
                });
                history.push("/dashboard");
            } else {
                setAlertstate({
                    open: true,
                    vertical: "bottom",
                    horizontal: "center",
                    message: "Login failed. Please try again.",
                    severity: "error",
                });
            }
        } catch (e) {
            setAlertstate({
                open: true,
                vertical: "bottom",
                horizontal: "center",
                message: "Invalid Data. Please try again.",
                severity: "error",
            });
        }
    };

  return (
    <Container component="main" maxWidth="xs">
      <CssBaseline />
      <div className={classes.paper}>
        <Avatar className={classes.avatar}>
          <LockOutlinedIcon />
        </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"
            onChange={(e) => {
                setLoginObj({ ...loginObj, username: e.target.value });
            }}
            autoFocus
          />
          <TextField
            variant="outlined"
            margin="normal"
            required
            fullWidth
            name="password"
            label="Password"
            type="password"
            id="password"
            onChange={(e) => {
                setLoginObj({ ...loginObj, password: e.target.value });
            }}
            autoComplete="current-password"
          />
          <FormControlLabel
            control={<Checkbox value="remember" color="primary" />}
            label="Remember me"
          />
          <Button
            type="button"
            fullWidth
            variant="contained"
            color="primary"
            onClick={handleSubmit}
            className={classes.submit}
          >
            Sign In
          </Button>
          <Grid container>
            <Grid item xs>
              <Link href="#" variant="body2">
                Forgot password?
              </Link>
            </Grid>
            <Grid item>
              <Link href="/signup" variant="body2">
                {"Don't have an account? Sign Up"}
              </Link>
            </Grid>
          </Grid>
        </form>
      </div>
      <Box mt={8}>
        <Copyright />
      </Box>
    </Container>
  );
}

axios.js


import axios from 'axios';
import history from "../history";
const apiUrl = 'https://mysite/api/auth'; //your api base url
const proxyurl = "https://myproxy.io/fetch/"; //proxy for local testing, remove this in production version
function getHeader() {
    const token = localStorage.getItem("token");
    const expiration = localStorage.getItem("token_exp");
    if (expiration * 1000 < Date.now()) {
        history.push("/");
        return {
            "Content-Type": "application/json",
        };
    }
    if (token) {
        return {
            Authorization: `Bearer ${token}`,
            "Content-Type": "application/json",
            useCredentials: true,
        };
    } else {
        return {
            "Content-Type": "application/json",
        };
    }
}
const api = axios.create({
    baseURL: apiUrl,
    headers: getHeader(),
})

export default api;
  

CodePudding user response:

You are mixing up async/await with promise handlers, use any one of them or remove the promise handlers (then, catch) from post call and it should work,

In current situation you won't be receiving data object, that's why you are facing this issue.

CodePudding user response:

it is because in the tokenAPICALL you are consuming your api call promise with both await and .then() in that case your response will be logged to the console but then destructuring (const {data} = ...) won't work.

try this:


    const {data} = await api.post(
      `/login`,
      {
        email: user,
        password: pass,
      },
      {
        method: 'POST',
        headers: {
          "Content-Type": "application/json; charset=UTF-8",
        },
      }
    )

  • Related