Home > OS >  Axios Post is not waiting in react so never goes into .then
Axios Post is not waiting in react so never goes into .then

Time:01-05

I am making a simple login authentication app using React and Fastapi. My axios post request used to work intially just as indended with the exact same code except I changed the UI slightly.

Basically react would send a post request to my server and then it would repsond with a session token if it authenticates. This worked before. I dont know why it does not work anymore.

I tried just returning a simple {"token": "hello"} and then that was stored properly, so I am assuming it is something to do with the time it takes. Basically react does not wait for the POST request to send a response and moves on and returns the html. The logs show that fastapi is returning the correct thing. It goes inside the .then but then does not go into the function (response) part of it.

react code for Login page

import { useNavigate } from "react-router";
import { fetchToken, setToken } from "./Auth";
import { useState } from "react";
import axios from "axios";

export default async function Login() {
  const navigate = useNavigate();
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  //check to see if the fields are not empty
  const login = () => {
    console.log(email, password);
    if ((email === "") & (password === "")) {
      return;
    } else {
      axios
        .post("http://localhost:8000/login", {
          email: email,
          password: password,
        })
        .then(function (response) {
          console.log(response.data.token, "response.data.token");
          if (response.data.token) {
            setToken(response.data.token);
            navigate("/profile");
          }
        })
        .catch(function (error) {
          console.log(error, "error");
        });
    }
  };
  
  return (
    <div>
      {fetchToken() ? (
        <p>you are logged in</p>
      ) : (
    <form>
      <h3>Sign In</h3>
      <div className="mb-3">
        <label>Email address</label>
        <input
          type="email"
          className="form-control"
          placeholder="Enter email"
          onChange={(e) => setEmail(e.target.value)}
        />
      </div>

      <div className="mb-3">
        <label>Password</label>
        <input
          type="password"
          className="form-control"
          placeholder="Enter password"
          onChange={(e) => setPassword(e.target.value)}
        />
      </div>

      <div className="d-grid">
        <button type="submit" className="btn btn-primary" onClick={login}>
          Submit
        </button>
      </div>

      <p className="forgot-password text-right">
          Not registered <a href="/sign-up">sign up?</a>
      </p>
      
    </form>
    )}
    </div>
  );
}

backend FastAPI code

from fastapi import FastAPI
import jwt
from pydantic import BaseModel, Field
from fastapi.encoders import jsonable_encoder
from fastapi.middleware.cors import CORSMiddleware
from pymongo import MongoClient
from bson import ObjectId
import certifi

# imported for mongo maybe
from fastapi import FastAPI, Body, HTTPException, status
from fastapi.responses import Response, JSONResponse

SECERT_KEY = "YOUR_FAST_API_SECRET_KEY"
ALGORITHM  = "HS256"
ACCESS_TOKEN_EXPIRES_MINUTES = 800

test_user = {
   "email": "temitope",
    "password": "temipassword",
}

url = "uri"
app = FastAPI()
client = MongoClient(url, tlsCAFile=certifi.where())
db = client.test

origins = {
    "http://localhost",
    "http://localhost:3000",
}

app.add_middleware(
   CORSMiddleware,
    allow_origins = origins,
    allow_credentials =True,
    allow_methods = ["*"],
    allow_headers= ["*"],
)

class LoginItem(BaseModel):
    email: str
    password: str

    @app.get("/")
    def read_root():
        return {"Hello": "World"}

    class Config:
        schema_extra = {
            "example": {
                "email": "devang@hello",
                "password": "encrypted"
            }
        }

class PyObjectId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if not ObjectId.is_valid(v):
            raise ValueError("Invalid objectid")
        return ObjectId(v)

    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")


class UserModel(BaseModel):
    id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
    firstName: str = Field(...)
    lastName: str = Field(...)
    email: str = Field(...)
    password: str = Field(...)

    class Config:
        allow_population_by_field_name = True
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}
        schema_extra = {
            "example": {
                "firstName": "Devang",
                "lastName": "Agrawal",
                "email": "devang@hello",
                "password": "encrypted"
            }
        }

#function to encode the user
def get_jwt(user:UserModel):

    #jsonify the user and delete the firstName and lastName and _id
    data = jsonable_encoder(user)
    print(data)
    del data['firstName']
    del data['lastName']
    del data['_id']
    print(data)
    return jwt.encode(data, SECERT_KEY, algorithm=ALGORITHM)

#function to retrieve user with the given encoded jwt token
def get_user(encoded_jwt):
    #look at all the users in the database
    users = db["users"].find()

    #check if the user exists in the database
    for user in users:
        if user['encoded_jwt'] == encoded_jwt:
            return user

@app.post("/login")
async def user_login(loginitem:LoginItem):

    #look at all the users in the database
    data = jsonable_encoder(loginitem)
    # return {"token": data["email"]}
    print(f"{data} is the data")

    #encode the user
    encoded_jwt = jwt.encode(data, SECERT_KEY, algorithm=ALGORITHM)

    #check if the user exists in the database
    if get_user(encoded_jwt) != None:
        print("success")
        return {"token": encoded_jwt}

    print("failed")
    return {"message": "login failed"}

@app.post("/add", response_description="Add new user", response_model=UserModel)
async def create_user(user: UserModel = Body(...)):

    #jsonify the userx
    user = jsonable_encoder(user)

    #encode the user and add it to the user object
    user['encoded_jwt'] = get_jwt(user)
    del user['password']
    print(user)

    #add the user to the database
    new_user = db["users"].insert_one(user)
    created_user = db["users"].find_one({"_id": new_user.inserted_id})

    #return success message
    return JSONResponse(status_code=status.HTTP_201_CREATED, content=created_user)

Does someone know how to make sure that the response is processed properly with axios post. Also I tried async and await, while setting random timeouts but nothing worked.

CodePudding user response:

Try to move the login function in the onSubmit event of the form:

<form onSubmit={login}>

Remove the onClick from the submit button:

<button type="submit" className="btn btn-primary">...</button>

And call e.preventDefault() before the execution:

const login = (e) => {
  e.preventDefault();

  console.log(email, password);
  if ((email === '') & (password === '')) {
    return;
  }
  
  axios
    .post('http://localhost:8000/login', { email, password })
    .then(function (response) {
      console.log(response.data.token, 'response.data.token');
      if (response.data.token) {
        setToken(response.data.token);
        navigate('/profile');
      }
    })
    .catch(function (error) {
      console.log(error, 'error');
    });
  }
};
  • Related