react native make accessToken global - react-native

im using rn-secure-storage to save authState when using oauth2, then i have class AppHelper to control all network function like below:
import RNSecureStorage, { ACCESSIBLE } from 'rn-secure-storage'
export const accessToken = async() => {
await RNSecureStorage.get("authState").then((value) => {
console.log("authState", value);
return JSON.parse(value).accessToken
}).catch((err) => {
console.log("can not get authState", err);
});
};
export const getData = (url, tag = 'getData') => {
return fetch(url, {
method : 'GET',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Authorization' : 'Bearer ' + accessToken
}
})
.then((response) => {
console.log(tag, 'Bearer ' + accessToken);
return response.text();
})
.then((json) => {
console.log(tag, json)
return json;
})
.catch((error) => {
handleError(err)
console.log(tag, error, url)
});
}
export const handleError = (error) => {
if (error.response.code == 401){
alert('Unauthorized')
}else{
console.log('network call failed', error)
}
}
im coding native before, so im not familiar with React native syntax. I just want to get access token to apply in network call, but my code show error:
_getMasterInfoApi Bearer function _callee() {
return _regenerator.default.async(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return _regenerator.default.awrap(_rnSecureStorage.default.get("authState").then(function (value) {
console.log("authState", value);
return JSON.parse(value).accessToken;
}).catch(function (err) {
handleError(err);
}));
case 2:
case "end":
return _context.stop();
}
}
}, null, null, null, Promise);
}
Can anyone help? thanks in advance

Related

React-native-fetch-blob GET request error

I am replacing axios to rn-fetch-blob in my react-native project. In the request I ping my server with credentials and I expect a response.
The old request with axios is as follows and works perfectly:
export const postWorkspace =
(newWorkspace: Workspace): AppThunk =>
async (dispatch) => {
console.log('addWorkspace Start');
dispatch(setIsLoading(true));
let configOption = {
headers: {
'Access-Control-Allow-Origin': '*',
'X-AUTH-USER': newWorkspace.credentials.email,
'X-AUTH-TOKEN': newWorkspace.credentials.password,
},
};
await axios
.get(`${newWorkspace.url}/api/ping`, configOption)
.then(async (resp) => {
console.log('addWorkspace resp', resp);
try {
await storeWorkspaceToStorage(newWorkspace);
} catch (e) {
console.error(e);
}
})
.catch((err) => {
console.log('addWorkspace err', JSON.stringify(err));
return Promise.reject(err);
})
.finally(() => dispatch(setIsLoading(false)));
};
This is how I transformed the code with rn-fetch-blob:
export const postWorkspace=
(newWorkspace: Workspace): AppThunk =>
async (dispatch) => {
console.log('addWorkspace Start');
dispatch(setIsLoading(true));
let configOption = {
'Access-Control-Allow-Origin': '*',
'X-AUTH-USER': newWorkspace.credentials.email,
'X-AUTH-TOKEN': newWorkspace.credentials.password,
};
await RNFetchBlob
.fetch('GET', '${newWorkspace.url}/api/ping', configOption)
.then( async(resp) => {
console.log('addWorkspace resp', resp);
try {
await storeWorkspaceToStorage(newWorkspace);
} catch (e) {
console.error(e);
}
})
.catch((err) => {
//console.log(err.info().status);
console.log('addWorkspace err', JSON.stringify(err));
return Promise.reject(err);
})
.finally(() => dispatch(setIsLoading(false)));
};
The new request with rn-fetch-blob returns this error:
response error "line":126349,"column":34,"sourceURL":"http://localhost:8081/index.bundle?platform=android&dev=true&minify=false"
When I opend the file "http://localhost:8081/index.bundle?platform=android&dev=true&minify=false" around line 1262349 the code looks like this, I can't understand what went wrong:
var req = RNFetchBlob[nativeMethodName];
req(options, taskId, method, url, headers || {}, body, function (err, rawType, data) {
subscription.remove();
subscriptionUpload.remove();
stateEvent.remove();
partEvent.remove();
delete promise['progress'];
delete promise['uploadProgress'];
delete promise['stateChange'];
delete promise['part'];
delete promise['cancel'];
promise.cancel = function () {};
//line 126349
if (err) reject(new Error(err, respInfo));else {
if (options.path || options.fileCache || options.addAndroidDownloads || options.key || options.auto && respInfo.respType === 'blob') {
if (options.session) session(options.session).add(data);
}
respInfo.rnfbEncode = rawType;
resolve(new FetchBlobResponse(taskId, respInfo, data));
}
});
});
I am doing this since rn-fetch-blob is basically one of the few libraries that allows react-native to ping a server with no SSL certification.
Thank you

How to passing result of http request inside async in ExpressJS?

I have below code
async send(user, data) {
const postData = {
'data': 'john',
'secret': 'secret'
};
const dataJson = JSON.stringify(postData);
const options = {
hostname: 'example.com',
path: '/send',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': dataJson.length
}
};
const req = https.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(dataJson);
req.end();
//---------------
let postResult = // HERE I WANT TO GET WHAT HTTP POST REQUESTED (e.g dataJson.body?)
//---------------
let result;
try {
result = await this.users.collection('users').updateOne(
{
_id: user
},
{
$set: {
// I WANT TO USE THAT HERE
data1 : postResult,
data2 : data2
}
},
{ maxTimeMS: consts.DB_MAX_TIME_USERS }
);
} catch (err) {
log.error('DB', 'UPDATEFAIL id=%s error=%s', user, err.message);
err.message = 'Database Error, failed to update user';
err.code = 'InternalDatabaseError';
throw err;
}
return { success: true };
}
How to get those data to outside variable?
I almost crazy about this, been searching on google and not found anything
I am using express and native-http to make http request, are there any native-curl maybe?
thank you very much for all the help
Your current code is using callback to retrieve result, so you can initiate data variable to outside callback function
let data = '';
const req = https.request(options, (res) => {
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
})
And also there are other easier way to make http request with nodejs. you can check axios that support Promise and async/await.
you can use syntax like this with axios
const response = await axios.get('/user?ID=12345');
way more easier.

React native asyncstorage cannot get data

I'm starting my react-native project with npm start. On my emulator I have installed expo to view my application. Also I'm using http://ip:19001/debugger-ui/ to debug my application in google chrome.
I don't know what I'm doing wrong but I can't get any data from asyncstorage. Can you please give me some tips how to correct this problem.
In one of my activities I store data with;
storeDataInAsync1(idSchool,year) {
try {
//await AsyncStorage.removeItem('user');
AsyncStorage.setItem('dateRange', this.props.range);
AsyncStorage.setItem('idSchool', idSchool);
AsyncStorage.setItem('school_year', year);
} catch (error) {
// Error saving data
}
}
My call to this method;
async saveMyProfil() {
var formData = new FormData();
formData.append('id_school',this.props.idSchool);
formData.append('school_year', this.props.year);
await fetch(`${api.url}/my_profile/`, {
method: 'POST',
headers: {
"Content-Type": "multipart/form-data"
},
body: formData,
}).then((response) => response.json())
.then((json) => {
console.log('Response: ' + JSON.stringify(json));
this.storeDataInAsync1(json.id_school,json.school_year);
//_storeData(json.id_school,json.school_year);
//this.doStuff(json.id_school,json.school_year);
})
.catch((error) => {
});
}
back() {
//this.storeDataInAsync();
this.saveMyProfil();
this.props.navigation.goBack();
}
In another activity there is method to retrive data;
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('idSchool');
const year = await AsyncStorage.getItem('school_year');
if (value !== null && year !== null) {
// We have data!!
console.log('Id School: ' + value);
console.log('Year: ' + year);
}
} catch (error) {
// Error retrieving data
}
}
I call _retrieveData in;
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
this._retrieveData();
}

AsyncStorage data changing upon app restart

I'm currently calling a JSON api to set an auth token which I'll just be storing in the AsyncStorage to persist between app life so a user doesn't have to log in every single time.
I'm currently setting that token like so:
fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(this.state)
})
.then( resp => {
return resp.json();
})
.then( async (data) => {
if ('error' in data) {
this.setState({
error: data.error,
password: ''
})
this.secondTextInput.focus();
}
if ('access_token' in data) {
try {
await AsyncStorage.setItem('access_token', data.access_token);
} catch (error) {
return error;
}
this.props.navigation.navigate('Main');
}
})
.catch(
error => {
console.error(error)
return error;
}
);
If I then call AsyncStorage.getItem('access_token') After killing the app or reloading it I'm winding up with this output:
{
"_40":0,
"_65":0,
"_55":null,
"_72":null
}
If I then call AsyncStorage.getItem('access_token') Before killing the app or reloading it I'm winding up with the correct access token. I've double checked the code and I'm not using AsyncStorage.setItem('access_token') anywhere else.
This is how I'm retrieving my token:
componentDidMount() {
console.warn('Mounting');
try {
let token = AsyncStorage.getItem('access_token');
console.warn(token);
if(token !== null) {
console.error(token);
}
} catch (error) {}
AsyncStorage.getItem() is a asynchronous action just like setItem(), so you need to wait until the Promise has been resolved before logging.
Edit
Tip: if you see some strange output like that it is always related to a Promise which is not yet resolved or rejected
I've solved my issue by using #dentemm's recommendation of creating an async function.
async _getToken() {
try {
var token = await AsyncStorage.getItem('access_token');
return token;
} catch(e) {
console.error(e);
}
}
componentDidMount() {
let token = null;
this._getToken()
.then( rsp => {
fetch(global.url + '/api/auth/refresh', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + rsp
}
})
.then(rsp => {
return rsp.json();
})
.then(data => {
if('access_token' in data) {
try {
AsyncStorage.setItem('access_token', data.access_token);
} catch (error) {
return error;
}
this.props.navigation.navigate('Main');
}
})
.catch( error => {
return error;
})
});
}
This way I can get my token from the storage then run my refresh function to get an updated token to use for future requests.

Using promise with GraphRequestManager

Does anyone have an example on how to use promise with GraphRequestManager?
I get Cannot read property then of undefined error in my action creator.
function graphRequest(path, params, token=undefined, version=undefined, method='GET') {
return new Promise((resolve, reject) => {
new GraphRequestManager().addRequest(new GraphRequest(
path,
{
httpMethod: method,
version: version,
accessToken: token
},
(error, result) => {
if (error) {
console.log('Error fetching data: ' + error);
reject('error making request. ' + error);
} else {
console.log('Success fetching data: ');
console.log(result);
resolve(result);
}
},
)).start();
});
}
I call the above using my action creator
export function accounts() {
return dispatch => {
console.log("fetching accounts!!!!!!");
dispatch(accountsFetch());
fbAPI.accounts().then((accounts) => {
dispatch(accountsFetchSuccess(accounts));
}).catch((error) => {
dispatch(accountsFetchFailure(error));
})
}
}
I get 'Success fetching data:' in the console along with the result before the error. So the API call is made successfully. The error is after fetching the accounts in fbAPI.accounts().then((accounts) which I think is due to GraphRequestManager returning immediately instead of waiting.
I have a solution for you.
My provider look like this :
FBGraphRequest = async (fields) => {
const accessData = await AccessToken.getCurrentAccessToken();
// Create a graph request asking for user information
return new Promise((resolve, reject) => {
const infoRequest = new GraphRequest('/me', {
accessToken: accessData.accessToken,
parameters: {
fields: {
string: fields
}
}
},
(error, result) => {
if (error) {
console.log('Error fetching data: ' + error.toString());
reject(error);
} else {
resolve(result);
}
});
new GraphRequestManager().addRequest(infoRequest).start();
});
};
triggerGraphRequest = async () => {
let result = await this.FBGraphRequest('id, email');
return result;
}
That works great ! I let you adapt my solution to your system.