i am having exsiting service to make api call through axios in my react app,which i think is limited to one api request at a time,i wanted to make multiple request using axios.all,but i am not able to find way to modify the service,see below is the code
As in Action.js you can see that i combine two request which is wrong i guess so,please help me how to combine two request using axios.all,and please suggest api service implementation is correct or what can i do to improve it
APIService.js
import axios from 'axios';
import apiConfig from './apiConfig';
import UserSession from './userSession';
import history from '../utils/history/history';
const session = sessionStorage;
var axiosConfig = axios.create({
baseURL: apiConfig.baseUrl,
headers: {
Authorization: sessionStorage.getItem('token') != null ?
`Bearer ${sessionStorage.getItem('token')}` : null,
Accept: 'application/json',
'Content-Type': 'application/json'
},
timeout: 20000,
responseType: 'json'
});
axiosConfig.interceptors.request.use((config) => {
config.headers.Authorization =
sessionStorage.getItem('token') != null ? `Bearer
${sessionStorage.getItem('token')}` : null;
return config;
},(error) => Promise.reject(error));
const apiService = function(options) {
const onSuccess = function(response) {
if (response.status === 201) {
return Promise.resolve(
Object.assign(
{},
{
message: response.statusText
}
)
);
} else if (response.status === 200) {
if ((response.data && response.data !== null) || response.data !==
undefined || response.data !== '') {
return response.data;
} else {
return Promise.resolve(
Object.assign(
{},
{
message: response.statusText
}
)
);
}
} else if (response.data.length < 1) {
return Promise.reject(
Object.assign(
{},
{
message: 'No Data'
}
)
);
} else {
return response.data;
}
};
const onError = function(error) {
if (error.response) {
if (error.response.status === 401) {
sessionStorage.removeItem('token');
window.location = '/login';
return Promise.reject(error.response);
} else if (error.response.status === 404) {
return Promise.reject(
Object.assign(
{},
{
message: error.response.statusText
}
)
);
} else if (error.response.status === 500) {
return Promise.reject(
Object.assign(
{},
{
message: error.response.statusText
}
)
);
} else {
return Promise.reject(error.response.data);
}
} else if (error.request) {
// The request was made but no response was received
return Promise.reject(
Object.assign(
{},
{
message: error.message
}
)
);
//return Promise.reject(error.message);
} else {
// Something else happened while setting up the request
// triggered the error
return Promise.reject(
Object.assign(
{},
{
message: error.message
}
)
);
}
};
return axiosConfig(options).then(onSuccess).catch(onError);
};
export default apiService;
Request.js
import apiService from '../apiService';
export const FirstRequest = () => {
return apiService({
url: 'FirstURL',
method: 'get',
});
};
export const SecondRequest = () => {
return apiService({
url: 'SecondURL',
method: 'get',
});
};
Action.js
export const SomeHandler = () => (dispatch) => {
dispatch({
type: API_REQUEST
});
FirstRequest()
.then((res) => {
dispatch({
type: API_SUCCESS
});
SecondRequest().then((res) => {
dispatch({
type: API_SUCCESS
});
dispatch({ type: VIEW1, payload: res });
dispatch({ type: VIEW2, payload: res });
}).catch((err) => {
dispatch({
type: API_FAILURE,
payload: err
});
});
})
.catch((err) => {
dispatch({
type: API_FAILURE,
payload: err
});
});
};
This is not related to axios at all. You can combine two async functions together in an action method, using async library:
async.parallel([
getUsers,
getComments
],
function(err, results) {
// the results array will equal to [[], {'x': 'y'}] even though
// the second function had a shorter timeout.
// dispatch here
});
function getUsers(callback) {
callback(null, [])
}
function getComments(callback) {
callback(null, {'x': 'y'})
}
First off, not sure you want to do this in your componentWillMount, because your component will not render until all this is done, it's better to have it in componentDidMount and have some default states that will update once done with these requests. Second, you want to limit the number of setStates you write because they might cause additional re-renders, here is a solution using async/await:
async componentDidMount() {
const firstRequest = await axios.get(URL1);
const secondRequest = await axios.get(URL2);
const thirdRequest = await axios.get(URL3);
this.setState({
p1Location: firstRequest.data,
p2Location: SecondRequest.data,
p3Location: thirdRequest.data,
});
}
i'm working this way. you can use this
const token_config = {
headers: {
'Authorization': `Bearer ${process.env.JWD_TOKEN}`
}
}
const [ res1, res2 ] = await Axios.all([
Axios.get(`https://api-1`, token_config),
Axios.get(`https://api-2`, token_config)
]);
res.json({
info: {
"res_1": res1,
"res_2": res2
}
});
Related
I am new to react native and making service call for the first time. My problem is service call is not going and getting warning like
Possible unhandled Promise Rejection, Reference error: response is not defined.
I am trying to hit loginUser function.
Api.js
const BASE_URL = "http://localhost:8200";
export const api = async (url, method, body = null, headers = {}) => {
try {
const endPoint = BASE_URL.concat(url);
const reqBody = body ? JSON.stringify(body) : null;
const fetchParams = {method, headers};
if((method === "POST" || method === "PUT") && !reqBody) {
throw new Error("Request body required");
}
if(reqBody) {
console.log("ReQBody--->"+reqBody);
fetchParams.headers["Content-type"] = "application/json";
fetchParams.body = reqBody;
}
const fetchPromise = await fetch(endPoint, fetchParams);
const timeOutPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("Request Timeout");
}, 3000);
});
const response = await Promise.race([fetchPromise, timeOutPromise]);
return response;
} catch (e) {
return e;
}
}
export const fetchApi = async (url, method, body, statusCode, token = null, loader = false) => {
console.log("In FetchAPi Function");
try {
const headers = {}
const result = {
token: null,
success: false,
responseBody: null
};
if(token) {
headers["securityKey"] = token;
}
const response = await api(url, method, body, headers);
console.log("fetchApi-->>"+response);
if(response.status === statusCode) {
result.success = true;
let responseBody;
const responseText = await response.text();
try {
responseBody = JSON.parse(responseText);
} catch (e) {
responseBody = responseText;
}
result.responseBody = responseBody;
return result;
}
let errorBody;
const errorText = await response.text();
try {
errorBody = JSON.parse(errorText);
} catch (e) {
errorBody = errorText;
}
result.responseBody = errorBody;
console.log("FetchApi(Result)--->>"+result);
throw result;
} catch (error) {
return error;
}
}
auth.actions.js
export const loginUser = (payload) => {
console.log("In LoginUser function2");
return async (dispatch) => {
<-----**I am not able to enter into this block**------>
try {
dispatch({
type: "LOGIN_USER_LOADING"
});
console.log("In LoginUser function3");
const response = await fetchApi("/login", "POST", payload, 200);
if(response.success) {
dispatch({
type: "LOGIN_USER_SUCCESS",
});
dispatch({
type: "AUTH_USER_SUCCESS",
token: response.token
});
dispatch({
type: "GET_USER_SUCCESS",
payload: response.responseBody
});
return response;
} else {
throw response;
}
} catch (error) {
dispatch({
type: "LOGIN_USER_FAIL",
payload: error.responseBody
});
return error;
}
}
}
In console log, I can't see anything in network tab. In the android emulator, the mentioned warning has come.
My console tab
I see that your BASE_URL is served using an http endpoint. You can only make requests to https endpoints from react native projects. A possible workaround is to use ngrok. Just download it and run ./ngrok http 8200 since your port number is 8200. It will expose an HTTPS endpoint and replace your BASE_URL with that link and try fetching the data again.
I use the following code to make API calls. See if you can integrate it in your code. it is quite simple:
In a class called FetchService:
class FetchService {
adminAuth(cb, data) {
console.log('here in the fetch service');
return fetch(
baseURL + "login",
{
method: "POST",
headers: {
Accept: "application/json",
},
body: data
}
)
.then((response) => response.json())
.then(responsej => {
cb(null, responsej);
})
.catch(error => {
cb(error, null);
});
}
}
export default FetchService;
Then call it from your component using:
import FetchService from './FetchService';
const fetcher = new FetchService;
export default class LoginScreen extends React.Component {
fetchData() {
const data = new FormData();
data.append('username',this.state.username);
data.append('password',this.state.password);
fetcher.wastereport((err, responsej) => {
if(err) {
//handle error here
} else {
//handle response here
}
}, data);
}
}
I am recreating the issue as I am not sure if that's a bug and a previous issue created for this just disappeared =/
Description
During an upgrade from react-admin v2 to v3.3.0, I encounter issue to get redirected to /login after rewriting the authProvider
react-admin documentation | github
My authProvider.js contains the following methods:
export default function createAuthProvider(urls, client, options) {
return {
login: (params) => {
return fetchLoginBatch(params, urls, client, options);
},
logout: (params) => params.jwt ? fetchLogout(makeRequestLogout(urls.logout, params.jwt), options) : Promise.resolve(),
checkError: (error) => {
const { status } = error;
if (status === 401 || status === 403) {
return Promise.reject();
}
return Promise.resolve();
},
checkAuth: (params) => params.jwt ? Promise.resolve() : Promise.reject(),
getPermissions: (params) => params.jwt ? Promise.resolve(params.jwt.authorities) : Promise.resolve(),
refreshJwt: (params) => params.jwt ? fetchRefreshJwt(makeRefreshJwtRequest(client.accessTokenUri, {
grant_type: 'refresh_token',
refresh_token: params.jwt.refresh_token,
}, client), options) : Promise.resolve()
};
}
It is as described in documentation and example
Expected
I expect to be redirected to /login.
Result
Instead, I stay on the page, checkAuth is well called and the jwt is null,
Possible fix
It is offered to change the redirect using an argument to rejected promise:
checkAuth: () => localStorage.getItem('token')
? Promise.resolve()
: Promise.reject({ redirectTo: '/no-access' }),
But adding Promise.reject({ redirectTo: '/login' }) doesn't help even if the code run.
I have tried to add some logging in ra-core/lib/sideEffect/auth.js:
console.log('auth');
exports.handleCheck = function (authProvider) {
console.log('handleCheck', authProvider);
return function (action) {
console.log('action', action);
var payload, meta, error_1, redirectTo, errorMessage;
console.log('redirectTo', redirectTo, 'meta', meta);
handleCheck is called but never action, it seems that the saga is ignored somehow.
Question
How should client side handle permissions and checkAuth rejection params ?
What should I check next to see why the redirection is failing?
How does the ra-core code follow?
Could you kindly scrutinize this line?
// authProvider.js
// checking if request has a JWT (this might be a typo!)
- checkAuth: (params) => params.jwt ? Promise.resolve() : Promise.resolve(),
// If not, we should reject thus triggering a redirect.
+ checkAuth: (params) => params.jwt ? Promise.resolve() : Promise.reject(),
Let me know how it works out.
Here is an example of authProvider, it works with both React-Admin 2 and React-Admin 3.3.1
Using:
<Admin authProvider={authProvider(loginUrl, logoutUrl)} ...>
import storage from './storage'
import {
AUTH_LOGIN,
AUTH_LOGOUT,
AUTH_ERROR,
AUTH_CHECK,
AUTH_GET_PERMISSIONS
} from 'react-admin'
import {
LB_TOKEN,
getTokenId
} from './token'
export const authProvider = (loginApiUrl, logoutApiUrl, noAccessPage = '/login') => {
return (type, params) => {
if (type === AUTH_LOGIN) {
const request = new Request(loginApiUrl, {
method: 'POST',
body: JSON.stringify(params),
headers: new Headers({ 'Content-Type': 'application/json' }),
})
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText)
}
return response.json()
})
.then(({ ttl, ...data }) => {
storage.save(LB_TOKEN, data, ttl)
return Promise.resolve(data)
})
}
if (type === AUTH_LOGOUT) {
const token = getTokenId()
if (token) {
storage.remove(LB_TOKEN)
if (logoutApiUrl) {
const request = new Request(`${logoutApiUrl}?access_token=${token}`, {
method: 'POST',
headers: new Headers({'Content-Type': 'application/json'}),
})
return fetch(request)
.then(response => {
if (response.status !== 204) {
console.error('authProvider - Logout, status:', response)
}
return Promise.resolve()
})
}
}
return Promise.resolve()
}
if (type === AUTH_ERROR) {
const { status } = params
if (status === 401 || status === 403) {
storage.remove(LB_TOKEN)
return Promise.reject()
}
return Promise.resolve()
}
if (type === AUTH_CHECK) {
const token = storage.load(LB_TOKEN)
if (token && token.id) {
return Promise.resolve()
} else {
storage.remove(LB_TOKEN)
return Promise.reject({ redirectTo: noAccessPage })
}
}
if (type === AUTH_GET_PERMISSIONS) {
const token = storage.load(LB_TOKEN)
if (token && token.user && token.user.roleId) {
return Promise.resolve(token.user.roleId)
} else {
console.warn('Unknown user rights:', token)
storage.remove(LB_TOKEN)
return Promise.reject({ redirectTo: noAccessPage })
}
}
return Promise.reject(`authProvider - Unknown method, type: ${type}, params: ${params}`)
}
}
I am a noob, using vue.js and a node auth api, the api works fine and provides the jwt token in the response, my question is how can i use the token in all the requests that follows (using axios), and any best practices for handling the token in the front end is also appreciated.
Thanks
You can use something like that for Your scenario in your vuejs app.
import axios from 'axios'
const API_URL = 'http://localhost:3000'
const securedAxiosInstance = axios.create({
baseURL: API_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
})
const plainAxiosInstance = axios.create({
baseURL: API_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
})
securedAxiosInstance.interceptors.request.use(config => {
const method = config.method.toUpperCase()
if (method !== 'OPTIONS' && method !== 'GET') {
config.headers = {
...config.headers,
'X-CSRF-TOKEN': localStorage.csrf
}
}
return config
})
securedAxiosInstance.interceptors.response.use(null, error => {
if (
error.response &&
error.response.config &&
error.response.status === 401
) {
return plainAxiosInstance
.post('/refresh', {}, { headers: { 'X-CSRF-TOKEN': localStorage.csrf } })
.then(response => {
localStorage.csrf = response.data.csrf
localStorage.signedIn = true
let retryConfig = error.response.config
retryConfig.headers['X-CSRF-TOKEN'] = localStorage.csrf
return plainAxiosInstance.request(retryConfig)
})
.catch(error => {
delete localStorage.csrf
delete localStorage.signedIn
location.replace('/')
return Promise.reject(error)
})
} else {
return Promise.reject(error)
}
})
export { securedAxiosInstance, plainAxiosInstance }
And in your component you use this to process your request with api
Products.vue
export default {
name: 'products',
data () {
return {
products: [],
newProduct: [],
error: '',
editedProduct: ''
}
},
created () {
if (!localStorage.signedIn) {
this.$router.replace('/')
} else {
this.$http.secured.get('/api/v1/products')
.then(response => { this.products = response.data })
.catch(error => this.setError(error, 'Something went wrong'))
}
},
methods: {
setError (error, text) {
this.error = (error.response && error.response.data && error.response.data.error) || text
},
addProduct () {
const value = this.newProduct
if (!value) {
return
}
this.$http.secured.post('/api/v1/products/', { product: { name: this.newProduct.name } })
.then(response => {
this.products.push(response.data)
this.newProduct = ''
})
.catch(error => this.setError(error, 'Cannot create product'))
},
removeProduct (product) {
this.$http.secured.delete(`/api/v1/products/${product.id}`)
.then(response => {
this.products.splice(this.products.indexOf(product), 1)
})
.catch(error => this.setError(error, 'Cannot delete product'))
},
editProduct (product) {
this.editedproduct = product
},
updateProduct (product) {
this.editedProduct = ''
this.$http.secured.patch(`/api/v1/products/${product.id}`, { product: { title: product.name } })
.catch(error => this.setError(error, 'Cannot update product'))
}
}
}
You can find here a lot of good patterns which I personally use on my projects and how also JWT token handling.
For saving token in a brower, you can use cookie, sessionStorage or localStorate, last one is the most popular now (short explination here).
In a few words, you can create an axion instance and add a token before request sent.
const http = axios.create({
baseURL: process.env.VUE_APP_SERVER_API,
// here you can specify other params
})
http.interceptors.request.use(request => {
// Do something before request is sent
request.headers['Authorization'] = `JWT ${TOKEN_HERE}`
// some logic what to do if toke invalid, etc ...
return request
}, function (error) {
// Do something with request error
return Promise.reject(error)
})
I'm using the library axios in my react app.
I'm having a problem with the interceptor.
My question is let say I have three requests happening concurrently and I don't have the token, the interceptor calling the getUserRandomToken three time, I want the interceptor will wait until I'm getting the token from the first request and then continue to the others.
P.S. the token he is with an expiration date so I also checking for it and if the expiration date is not valid I need to create a new token.
This is the interceptor:
axios.interceptors.request.use(
config => {
/*I'm getting the token from the local storage
If there is any add it to the header for each request*/
if (tokenExist()) {
config.headers.common["token"] = "...";
return config;
}
/*If there is no token i need to generate it
every time create a random token, this is a axios get request*/
getUserRandomToken()
.then(res => {
/*add the token to the header*/
config.headers.common["token"] = res;
return config;
})
.catch(err => {
console.log(err);
});
},
function(error) {
// Do something with request error
return Promise.reject(error);
}
);
How about singleton object that will handle the token generations? something similar to this:
const tokenGenerator ={
getTokenPromise: null,
token: null,
getToken(){
if (!this.getTokenPromise){
this.getTokenPromise = new Promise(resolve=>{
/*supposed to be a http request*/
if (!this.token){
setTimeout(()=>{
this.token = 'generated';
resolve(this.token);
},0)
}else{
resolve(this.token);
}
})
}
return this.getTokenPromise;
}
you can reference this same object from the interceptors.
see example: JS FIddle
reference: reference
You can return a Promise from interceptor callback to "wait" until promise fullfiles (this will fit your case). Check out this example:
function axiosCall () {
return new Promise((resolve, reject) => {
Axios.post(URL, {apiKey}).then((response) => {
resolve(response.data.message);
}).catch((error) => {
reject(error);
});
});
}
instance.interceptors.request.use((config) => {
return axiosCall().then((tokenResponse) => {
setWebCreds(tokenResponse);
config.headers.Authorization = `Bearer ${tokenResponse}`;
return Promise.resolve(config)
}).catch(error => {
// decide what to do if you can't get your token
})
}, (error) => {
return Promise.reject(error);
});
More details here: https://github.com/axios/axios/issues/754
Following code doing certain tasks:
Update Token on 401
Make a queue of failed requests while the token is refreshing.
Restore the original request after token refreshing.
Once the peculiar request is given 200, remove it from the queue.
Config.js
import axios from 'axios';
import { AsyncStorage } from 'react-native';
import { stateFunctions } from '../../src/sharedcomponent/static';
const APIKit = axios.create({
baseURL: '',
timeout: 10000,
withCredentials: true,
});
const requestArray = [];
// Interceptor for Request
export const setClientToken = token => {
APIKit.interceptors.request.use(
async config => {
console.log('Interceptor calling');
let userToken = await AsyncStorage.getItem('userToken');
userToken = JSON.parse(userToken);
config.headers = {
'Authorization': `Bearer ${userToken}`,
'Accept': 'application/json',
"Content-Type": "application/json",
"Cache-Control": "no-cache",
}
// console.log('caling ' , config)
return config;
},
error => {
Promise.reject(error)
});
};
// Interceptor for Response
APIKit.interceptors.response.use(
function (response) {
if (requestArray.length != 0) {
requestArray.forEach(function (x, i) {
if (response.config.url == x.url) {
requestArray.splice(i, 1);
}
});
}
return response;
},
function (error) {
const originalRequest = error.config;
requestArray.push(originalRequest);
let reqData = "username=" + number + "&password=" + pin + "&grant_type=password" + "&AppType=2" + "&FcmToken=null";
// console.log('error ' , error);
if (error.message === "Request failed with status code 401" || error.statuscode === 401) {
if (!originalRequest._retry) {
originalRequest._retry = true;
return axios({
method: 'post',
url: '/api/login',
data: reqData,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Cache-Control": "no-cache",
}
})
.then(res => {
let response = res.data;
console.log('successfull Login', response)
if (res.data.StatusCode == 200) {
AsyncStorage.setItem('userToken', JSON.stringify(response.access_token));
stateFunctions.UserId = response.UserId;
stateFunctions.CustomerContactID = response.CustomerContactID;
let obj = {
access_token: response.access_token,
token_type: response.token_type,
expires_in: response.expires_in,
UserId: response.UserId,
CustomerContactID: response.CustomerContactID,
Mobile: response.Mobile,
StatusCode: response.StatusCode
}
AsyncStorage.setItem('logindetail', JSON.stringify(obj));
if (requestArray.length != 0) {
requestArray.forEach(x => {
try {
console.log(x, "request Url");
x.headers.Authorization = `Bearer ${response.access_token}`;
x.headers["Content-Type"] = "application/x-www-form-urlencoded";
APIKit.defaults.headers.common["Authorization"] = `Bearer${response.access_token}`;
APIKit(x)
} catch (e) {
console.log(e)
}
});
}
return APIKit(originalRequest);
}
})
.catch(err => {
console.log(err);
});
}
}
return Promise.reject(error);
}
);
export default APIKit;
Home.js
gettingToken = async () => {
let userToken = await AsyncStorage.getItem('userToken');
userToken = JSON.parse(userToken);
await setClientToken(userToken);
}
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
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>
)
}
}
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}
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
}}