1

I am creating a mock login button which will return a user object after 5 seconds of clicking the login button.

I have the following event handler for the login button:

import UserService from "../services/user";

export default class Login extends Component {
  constructor(props) {
    super(props);

    this.state = {
      field: {
        username: "",
        password: "",
      },
    };
  }
  
  login = async (event) => {
    event.preventDefault();
    const res = await UserService.login({
      username: this.state.field.username,
      password: this.state.field.password,
    });
    console.log("RESPONSE DATA", res);
    // Set user variable to the response
  };

And this is the user service:

let user = null;

const login = async (credentials) => {
  await setTimeout(() => {
    user = {
      name: "test user",
      username: credentials.username,
      password: credentials.password,
      token: "test token",
    };
    console.log("login service finished");
  }, 5000);
  return user;
};

Basically, I want the user object to appear on the console.log("RESPONSE DATA", res) part. However, what I'm getting instead is null. How do I go around on doing this properly?

================================== EDIT: Decided to rewrite into function components. I'm still getting the same results

const Login = () => {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const userContext = useContext(UserContext);

  const login = async (event) => {
    event.preventDefault();
    console.log("logging in:", username, password);
    try {
      const user = await UserService.login({
        username: username,
        password: password,
      });
      console.log(user);
      // userContext[1](user);
      // console.log(userContext);
    } catch (exception) {
      console.log(exception);
    }
  };
demiglace
  • 405
  • 1
  • 5
  • 12

1 Answers1

2

The main issue here is that setTimeout return value is basically

a positive integer value which identifies the timer created by the call to setTimeout(). (which can be passed to clearTimeout() to cancel the timeout)

So in order to achive this you need to transform your function so it returns a promise. You can find some options here. In your case you could edit it slightly the answers so do something like:

let user = null;

const login = async (credentials) => {
  return new Promise(resolve => setTimeout(() => {
    user = {
      name: "test user",
      username: credentials?.username,
      password: credentials?.password,
      token: "test token",
    };
    console.log("login service finished");
    return resolve(user);
  }, 5000))
};
Berci
  • 2,876
  • 1
  • 18
  • 28
  • 1
    This one solved my question. Further expanding into this answer, we can only await a Promise, that's why we needed to wrap the setTimeout function in a Promise. – demiglace Oct 28 '21 at 08:25