How to implement a callback function in React Native?

Viewed 20441

I'm just wondering how to implement callback function in onPress function. I want to make sure the first function completed then the second process triggered.

onPress={() => {
          onSignIn(); //run this function first
          if(_values.success == 1){ //then run this after onSignIn() function completed
            navigation.navigate("SignedIn");
          } 
        }}

onSignIn()

export const onSignIn = async () => {
  if (_values.username && _values.password) { 
    fetch("http://localhost:3001/sessions/create", {
      method: "POST",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username: _values.username,
        password: _values.password
      })
    })
    .then((response) => response.json())
    .then((responseData) => {
      if(responseData.access_token){
         AsyncStorage.setItem(USER_KEY, responseData.access_token);
        _values.success = 1;
        alert("Login successfully!");
        return _values.success;
      } else {
        alert("Wrong username and password!");
        _values.success = 0;
        return _values.success;
      }
    })
    .done();
  } else{
    alert("Please enter your username and password.");
  }
}

Reference: https://github.com/datomnurdin/auth-reactnative

4 Answers

Return a Promise from the method and add .then() to the function call

export const onSignIn = async () => {

  const promise =  new  Promise(async (resolve, reject) => {

    try {
    //do something and return result on success
    resolve(result);

   }catch(msg) { reject(msg);}

   });

  return promise;
}

Call the method like this:

onSignIn ().then(
     (response,error) => {
     //get callback here
  });

By "wait for onSignIn to complete" I guess you mean it is an asynchronous function, you can then use the await operator to wait for it to be over

onPress={() => {
        await onSignIn(); //run this function first
        if(_values.success == 1){ //then run this after onSignIn() function completed
            navigation.navigate("SignedIn");
        } 
    }}

Then you will ahve to add async to your onSignIn function :

onSignIn = async () => {console.log("signing in")}

Here is a more 'React-y' way too handle your full process :

import React, { Component } from 'react'

export default class Example extends Component {

    onSignIn = async () => {
        console.log('singing in....')
    }

    pressEvent = async event => {
        await this.onSignIn(); //run this function first
        if (_values.success == 1) { //then run this after onSignIn() function completed
            navigation.navigate("SignedIn");
        }
    }

    render() {
        return (
            <div onPress={this.pressEvent}>

            </div>
        )
    }
}

EDIT :

Instead of returning a 0 or a 1, you could simply return a boolean in your function. Also, now that you are using the more modern async/await operators, you can remove the then functions :

export const onSignIn = async () => {
    if (_values.username && _values.password) {
        const response = await fetch("http://localhost:3001/sessions/create", {
            method: "POST",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                username: _values.username,
                password: _values.password
            })
        })
        const responseData = JSON.parse(response)
        if (responseData.access_token) {
            AsyncStorage.setItem(USER_KEY, responseData.access_token);
            alert("Login successfully!");
            return true
        } else {
            alert("Wrong username and password!");
            return false
        }
    } else {
        alert("Please enter your username and password.");
    }
}

Now, here is how you will fetch the response from this function :

export default class Example extends Component {

    pressEvent = async event => {
        if (await onSignIn()) navigation.navigate("SignedIn");
    }

    render() {
        return (
            <div onPress={this.pressEvent}>

            </div>
        )
    }
}

first, onSign() must be an async function, don't add the done() function,you want to handle it latter:

  export const onSignIn = async () => {
  if (_values.username && _values.password) { 
    fetch("http://localhost:3001/sessions/create", {
      method: "POST",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username: _values.username,
        password: _values.password
      })
    })
    .then((response) => response.json())
    .then((responseData) => {
      if(responseData.access_token){
         AsyncStorage.setItem(USER_KEY, responseData.access_token);
        _values.success = 1;
        alert("Login successfully!");
        return _values.success;
      } else {
        alert("Wrong username and password!");
        _values.success = 0;
        return _values.success;
      }
    })
  } else{
    throw "Please enter your username and password.";
  }
}

then, you just do:

onPress={() => {
          onSignIn().then( (values) => {
            if(values.success == 1){
               navigation.navigate("SignedIn");
            } 
          })
          .catch(error => console.log(error)) //do something in case onSignIn fails 
        }}

This code should help you

async onPressFunc() {
  await onSignIn(); //run this function first

  if(_values.success == 1){ //then run this after onSignIn() function completed
    navigation.navigate("SignedIn");
  } 
}

onPress={this.onPressFunc}
Related