Headers lost in chained fetch request [React-Native] - api

I'm currently trying to chain API requests to retrieve user information with React Native. The problem that I am running into is that the first fetch request goes provides the response that I'm looking for, but the chained request hangs up.
I've been able to narrow this down by running the API on my machine and here's what the problem is. When the first request is made, the headers in the config object are passed through without issue. When the second request is made, the X-Tenant-Name header is passed through, but for some reason the Authorization header is lost in the process, and therefore the request fails.
Here's the function making the requests:
async componentWillMount() {
const { authToken, selectedUser, tenant } = this.props;
const config = {
method: 'GET',
headers: {
'X-Tenant-Name': tenant,
'Authorization': 'Bearer ' + authToken
}
}
await fetch(URL + '/users/' + selectedUser.id, config)
.then(response => response.json())
.then(response => {
this.setState({ user: response.data });
const children = response.data.relationships.following_tips.data;
if (children.length) {
for (let i = 0; i < children.length; i++) {
fetch(URL + '/tips/' + children[i].id, config)
.then(response => response.json())
.then(response => console.log(response))
.done();
}
}
})
.done();
}
Any ideas?

I think your problem is being caused because your are forgetting to pass config to the second fetch. Try this one:
async componentWillMount() {
const { authToken, selectedUser, tenant } = this.props;
const config = {
method: 'GET',
headers: {
'X-Tenant-Name': tenant,
'Authorization': 'Bearer ' + authToken
}
}
await fetch(URL + '/users/' + selectedUser.id, config)
.then(response => response.json())
.then(response => {
this.setState({ user: response.data });
const children = response.data.relationships.following_tips.data;
if (children.length) {
for (let i = 0; i < children.length; i++) {
fetch(URL + '/tips/' + children[i].id, config) //Add config to this fetch too.
.then(response => response.json())
.then(response => console.log(response))
.done();
}
}
})
.done();
}

Related

Getting 'Undefined' value outside Fetch API

I am new in react native, trying to assign fetch API response value to a local variable. But outside function shows an undefined value of the variable.
Here is code
const {
diesel_data
} = this.state
let currentHMR
let previous_HMR
let previous_EstEngHours
let isViolationPass_HMR
let asset_id = diesel_data[0].diselRequisitionDetails[0].asset_id
let current_hmr = diesel_data[0].diselRequisitionDetails[0].current_hmr
let requisitionId = diesel_data[0].requisitionId
this._indicator.startActivity()
fetch(url + 'Norms/DieselHmrViolation/' + asset_id + '/' + current_hmr + '/' + requisitionId, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => response.json())
.then((json) => {
this._indicator.stopActivity()
var list = json;
console.log(list)
if (!isBlank(list)) {
currentHMR = list.currentHMR
previous_HMR = list.previous_HMR
previous_EstEngHours = list.previous_EstEngHours
isViolationPass_HMR = list.isViolationPass_HMR
}
})
.catch((error) => {
console.error(error);
});
console.log('currentHMR', currentHMR)
I think you can do like this, wait until executing fetch (maybe you have to move this inside a async function)
let data;
await fetch('https://reqres.in/api/users/2', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
})
.then(res => res.json())
.then(res => data = res)
.catch(err => console.log(err))
console.log('data', data);

Struggling to correctly make use of returned values from functions that are being called Asynchronously by Axios

I have an Express server which serves as an API Request forwarding tool (i.e my client calls the express server, and the express server forwards that call to another API).
The way this server is supposed to work is that there is a single entry point which makes a request, and then based on the response makes further API requests and returns a result based on the combo of API request responses.
To be clearer, the main logic is as follows:
Single entry point, which makes an async axios call to get an ID value
Within this function, we call an async function, getPartnerDetails (passing that ID as the parameter)
getPartnerDetailscalls a 3rd async function, '''getRawJson''' which is supposed to return the final required result, passing it back to '''getPartnerDetails''' which then passes it to the main entry point.
Whats going wrong is that the results are being recieved but are not being pass back correctly. The console logs within the '''.then(()=>{})''' of my async functions are coming back as '''undefined'''.
Code below:
app.post('/checkuser', async (req, res, next) => {
const { man, bfn, bln, bsn, bc, bs, bz, bco } = req.body;
const bodyContent = {
man: man,
bfn: bfn,
bln: bln,
bsn: bsn,
bc: bc,
bs: bs,
bz: bz,
bco: bco,
profile: 'DEFAULT',
};
try {
await axios
.post('https://host.com/im/account/consumer', bodyContent, { headers })
.then((response) => {
const addressValidResult = response.data.score.etr.filter(
(result) => result.test === '19:2'
)[0];
// console.log(res.json(result.details));
const requestId = response.data.mtid;
const currentValidAddress = getPartnerDetails(requestId).then(
(result) => {
console.log('this is currentvalidaddress ' + result);
res.json({
validationMessage: addressValidResult,
currentValidAddress: result,
});
}
);
})
.catch((err) => next(err));
} catch {}
});
async function getPartnerDetails(appId) {
let config = {
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic M2QzMsdfsslkfglkdjfglkdjflkgd',
},
params: {
partner: 19,
},
};
const res = await axios
.get(
`https://host.com/im/account/consumer/${appId}/partner/requests`,
config
)
.then((response) => {
const requestId = response.data.requests[0].request_id;
console.log('this is request id ' + JSON.stringify(requestId));
const raw = getRawJson(appId, requestId).then((result) => {
console.log('this is getRawJson result ' + JSON.stringify(result));
return JSON.stringify(result);
});
// https://host.com/im/account/consumer/:appId/partner/request/:requestId
})
.catch((err) => console.log('err2' + err));
}
async function getRawJson(appId, requestId) {
const res = await axios
.get(`host.com/im/account/consumer/${appId}/partner/request/${requestId}`, {
headers,
})
.then((response) => {
console.log('this is response ' + JSON.stringify(response.data));
return JSON.stringify(response.data);
})
.catch((err) => console.log('err1 ' + err));
}
It might have something to do with how I'm using async and await, I'm new to it so I'm hoping that I'll learn a thing or 2 more about it by solving this project.
I'm also aware that maybe I should split the entry point out into 3 different entry points, and have the client manage the chaining of the requests and responses instead.
Thanks!!
Probably an error due to incorrect async await usage.
Try to change your code like this:
app.post('/checkuser', async (req, res, next) => {
const { man, bfn, bln, bsn, bc, bs, bz, bco } = req.body;
const bodyContent = {
man: man,
bfn: bfn,
bln: bln,
bsn: bsn,
bc: bc,
bs: bs,
bz: bz,
bco: bco,
profile: 'DEFAULT',
};
try {
const { data } = await axios.post(
'https://host.com/im/account/consumer',
bodyContent,
{ headers }
);
const addressValidResult = data.score.etr.filter(
(result) => result.test === '19:2'
)[0];
const requestId = data.mtid;
const currentValidAddress = await getPartnerDetails(requestId);
console.log('this is currentvalidaddress ' + currentValidAddress);
res.json({
validationMessage: addressValidResult,
currentValidAddress: currentValidAddress,
});
} catch (err) {
next(err);
}
});
async function getPartnerDetails(appId) {
let config = {
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic M2QzMsdfsslkfglkdjfglkdjflkgd',
},
params: {
partner: 19,
},
};
const { data } = await axios.get(
`https://host.com/im/account/consumer/${appId}/partner/requests`,
config
);
const requestId = data.requests[0].request_id;
console.log('this is request id ' + JSON.stringify(requestId));
return getRawJson(appId, requestId);
}
function getRawJson(appId, requestId) {
return axios
.get(`host.com/im/account/consumer/${appId}/partner/request/${requestId}`, {
headers,
})
}

How should i use asyncstorage.setItem in this fetch method?

i want to add the async storage method to save my json response,
but i don't know how to add there specifically
i have already tried like this
UserRegisterationFunction = () => {
const { UserName } = this.state;
const { UserEmail } = this.state;
const { UserPassword } = this.state;
fetch('http://192.168.1.7/test/user_registration.php', {
method: 'POST',
headers: {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
body: JSON.stringify({
name: UserName,
email: UserEmail,
password: UserPassword
})
}).then((response) => response.json())
.then((responseJson) => {
AsyncStorage.setItem('token', responseJson)
// this._onValueChange(STORAGE_KEY, responseData.id_token),
Alert.alert(responseJson);
}).catch((error) => {
console.log(error)
});
i am getting my alert successfully but i don't know how should i add the responseJson or if i have used it correctly or not
You can use the asynchronous system or save successfully without using it.
To run asynchronously:
.then(async (responseJson) => {
await AsyncStorage.setItem('token', responseJson.id_token);
Alert.alert(responseJson);
}).catch((error) => {
console.log(error)
});
If your responseJson data is this:
Object {
id_token : "myid"
}
Use the getItem function on the following screen to check the value.
async componentDidmount() {
const tokens = await AsyncStorage.getItem('token');
alert(tokens); // You can see 'myid'
}
The JSON response is an object and you can't store the object directly in AsyncStorage. You can only store the object by converting it into a string.
To store the object:
AsyncStorage.setItem('KEY', JSON.stringify(object))
To retrieve the object:
const jsonObjectString = AsyncStorage.getItem('KEY')
const jsonObject = JSON.parse(jsonObjectString)

React Native fetch doesn't work in another fetch callback

If I call my api function from POINT 1, fetch method inside the api method works well. When I comment it out and call the function at POINT 2 fetch method inside the addAccount() doesn't work. There is no exception, no rejection, no request on Reactotron, even I can't find request over Charles Proxy. What is the difference and what I have to know to figure it out?
I tried with RN 0.55.2 and 0.57.5
// Auth.js typical react native component
import * as api from '../actions/api';
class Auth extends Component {
// first triggered function
loginAccount(){
// api.addAccount(); // POINT 1 - this line works well if I uncomment
fetch('https://domain-a.com/login/',{
method: 'POST',
credentials: "same-origin",
headers: {
'accept-language': 'en-US;q=1',
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: encodeURIComponent(bodyParameters)
}).then((response) => {
console.log(response);
return response.json()
}).then(({ status, invalid_credentials }) => {
if(status == "ok"){
CookieManager.get('https://domain-a.com')
.then((cookies) => {
this.fetchAccountData(cookies);
})
})
}
fetchAccountData(cookies){
fetch('https://domain-a.com/'+cookies.user_id+'/info/',{
method: 'GET',
headers: {
'cookie': cookies
}
}).then((response) => {
return response.json();
})
.then(({ user, status }) => {
api.addAccount(); // POINT 2 - this line doesn't work
});
}
}
// api.js
// I repleaced fetch code with document example just to be clearify
export const addAccount = () => {
console.log("fetch begin"); // always works
fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson); // won't works from point 2
})
.catch((error) =>{
console.error(error); // never runs
});
}
It looks like your first .then statement in the addAccount() function is missing a return statement. responseJson would be undefined without a proper a 'return response.json()' statement. Also adding brackets for better semantic formatting.
export const addAccount = () => {
console.log("fetch begin"); // always works
fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => {
console.log(response); //test this response
return response.json();
})
.then((responseJson) => {
console.log(responseJson); // won't works from point 2
})
.catch((error) =>{
console.error(error); // never runs
});
}

get item from asyncstorage in constructor and pass it to other method - react native

I have a file called Server.js in which I have written parent method to make get and post request. I am trying to extract few items from async-storage in the constructor and passing it to a method where I am assigning it to another variable. Now I have to use this variable inside my get and post method but unable to access the new variables(which are declared inside the constructor itself).
These new initialized variables are accessible by post method, but not inside the get method. When I tried some other workaround, it says that all my 3 variables ( participantId, mobeToken, urlAsync are undefined. Any input on my above issue.
variables :
1. participantId: will be sent as a header attribute (for authentication).
2. mobeToken: token for authentication, sent in Get request just like participantId.
3. urlAsync: its the url in which all the calls will be made. Once this is accessible inside Get and post method, I will remove this.baseUrl from both, Get & Post method request.
import React, { Component } from "react";
import { Alert,AsyncStorage} from 'react-native';
import axios from "axios";
const DEV_ENV_URL = "http://www.aaa.com/api";
const STAGE_ENV_URL = "http://www.bbb.com/api";
const PROD_ENV_URL = "http://www.ccc.com/api";
export default class Server extends Component {
baseUrl = DEV_ENV_URL;
constructor(props) {
super(props);
mobeToken1 = "";
participantId1 = "";
urlAsync = "";
AsyncStorage.getItem("profile", (err, res) => {
if (res !== null) {
let profile = JSON.parse(res);
participantId = profile.participantId;
} else {
profile = "";
}
AsyncStorage.getItem("mobeToken", (err, mobeToken) => {
AsyncStorage.getItem("URL", (err, Url) => {
this.assignValues(participantId, mobeToken, Url);
});
});
});
}
assignValues(participantId, mobeToken, Url) {
participantId1 = participantId;
mobeToken1 = mobeToken;
urlAsync = Url;
console.log("mobeToken1 "+ mobeToken1 + "," + participantId1 +"," + urlAsync);
}
getRequest(url) {
// debugger;
console.log(mobeToken1); // need variables in this method but can't
return fetch(this.baseUrl + url , {
method: 'GET',
headers: {
}
})
.then(response => response.json())
.then(responseJson => {
console.log(responseJson);
return responseJson;
})
.catch(error => {
console.log(error);
Alert.alert("", "Network connection issue. Please contact support");
});
}
postRequest(url, jsonData) {
return fetch(this.baseUrl + url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
// 'Content-Type': 'application/text',
"parse-array": "|entryJSONList|",
"mobeToken": mobeToken1,
"participantId": participantId1,
},
body: JSON.stringify(jsonData)
})
.then(response => response.json())
.then(responseJson => {
console.log(responseJson);
return responseJson;
})
.catch(error => {
console.log(error);
Alert.alert("", "Network connection issue. Please contact support");
});
}
}
Is there any alternative solution for this?
Thanks for viewing or providing solutions to this....