skip to Main Content

I need to call multiple async functions to complete a user login in my React Native app. The problem is, my login is dispatched before these async functions complete, and the home screen is loaded before the data from my API is fully saved. This is the part of my code that is fetching API data and dispatching sign in:

// Login and retrieve the authtoken, username, and uid, then save to SecureStore
await axios.post(
    '/login', 
    JSON.stringify({
        'username': data.username,
        'password': data.password
    }),
    {
        headers: {'Content-Type': 'application/json'}
    }
)
.then(res => {
    // Save uid, auth token, and username to securestore
    // These need to complete before dispatching SIGN_IN
    saveUserInfo(res.data.uid, res.data.token, data.username);
    getAppScreensFromAPI(res.data.token, res.data.uid);
    dispatch({ type: 'SIGN_IN', token: res.data.token });
})

How can I structure this code to finish the async functions before dispatching the SIGN_IN? I want to setup a state to display a loading screen while this is happening in the background, but I am not sure how to write in code when my async functions have finished.

Here is the code for the async functions I am using in my .then() :

// Save the uid, auth token, and username to SecureStore
async function saveUserInfo(uid, token, username) {
  // Convert all user info to String data type before saving to SecureStore
  let uid_str = uid.toString();
  let token_str = token.toString();
  let username_str = username.toString();

  await SecureStore.setItemAsync('userToken', token_str);
  await SecureStore.setItemAsync('username', username_str);
  await SecureStore.setItemAsync('uid', uid_str)
}

export async function getAppScreensFromAPI(userToken, uid) {
  const response = await axios.get(
    ('/personnel/app_screens/' + uid),
    {
      headers: {'Authorization': 'Token ' + userToken}
    }
  )

  // Save the JSON data for the app_screens list as a string to be parsed later
  await AsyncStorage.setItem('app_screens', JSON.stringify(response.data));

  // Return the app_screens array
  return response.data.app_screens;
}

I apologize if my code is a mess, this has been a frustrating learning process. I think I am misunderstanding how async functions work, but I’m having trouble finding the information I need.

2

Answers


  1. You could make the then callback async to execute functions in order

    // Login and retrieve the authtoken, username, and uid, then save to SecureStore
    await axios.post(
        '/login', 
        JSON.stringify({
            'username': data.username,
            'password': data.password
        }),
        {
            headers: {'Content-Type': 'application/json'}
        }
    )
    .then(async res => {
        // Save uid, auth token, and username to securestore
        // These need to complete before dispatching SIGN_IN
        await saveUserInfo(res.data.uid, res.data.token, data.username);
        await getAppScreensFromAPI(res.data.token, res.data.uid);
    
        dispatch({ type: 'SIGN_IN', token: res.data.token });
    })
    
    Login or Signup to reply.
  2. In your example after ‘then’ your code is running synchronously, you need to make those instructions after then running asynchronously for instance:

    // Login and retrieve the authtoken, username, and uid, then save to SecureStore
    try {
        const res = await axios.post(
            '/login',
            JSON.stringify({
                'username': data.username,
                'password': data.password
            }), {
                headers: {
                    'Content-Type': 'application/json'
                }
            }
        )
        // Save uid, auth token, and username to securestore
        // These need to complete before dispatching SIGN_IN
        await saveUserInfo(res.data.uid, res.data.token, data.username);
        await getAppScreensFromAPI(res.data.token, res.data.uid);
    
        dispatch({
            type: 'SIGN_IN',
            token: res.data.token
        });
    } catch (err) {
        console.log(err);
        //Maybe dispatch an error here
        //dispatch({ type: 'SIGN_IN_ERROR', err });
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search