Console.log useState causes it to fire multiple times - React Native - react-native

I have the following function. If I try to console.log locationData my console gets overflooded because it logs it multiple times.
function GetGoogleData(){
const [locationData,setLocationData] = React.useState(undefined);
let APIURL = `https://maps.googleapis.com/maps/api/place/details/json?placeid=${locationID}&key=xxxxxxxxxxxxxxxxxxxxxxxxxxx`;
let headers = {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
};
fetch(APIURL,{
method: 'POST',
headers: headers,
})
.then((Response)=>Response.json())
.then((Response)=>{
setLocationData(JSON.stringify(Response))
});
console.log(LocationData)
}

Have a try by moving the API call inside the Life Cycle hook useEffect of React.
Ex.
function GetGoogleData(){
const [locationData,setLocationData] = React.useState(undefined);
useEffect(() => {
let APIURL = `https://maps.googleapis.com/maps/api/place/details/json?placeid=${locationID}&key=xxxxxxxxxxxxxxxxxxxxxxxxxxx`;
let headers = {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
};
fetch(APIURL,{
method: 'POST',
headers: headers,
})
.then((Response)=> Response.json())
.then((Response)=>{
setLocationData(JSON.stringify(Response))
});
}, [])
useEffect(() => {
if (locationData) {
console.log('locationData : ', locationData)
}
}, [locationData])
}
The first useEffect will only executed first mount of component and the second useEffect will call every update of the locationData State changes.

Related

How to properly await Nuxt calls with async/await or .then

Im trying to fetch an API using chaining with .then but I don't figure it out I try like:
async fetch() {
let path = this.$nuxt.context.route.path
this.response = await axios.get(
`/api${path}`,
{
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json'
}
}
).then((res) => {
this.results = res.data.content.slice(0,40);
return results();
})
.then((res) => {
this.results2 = res.data.content.slice(20,40);
return results2();
})
},
For my API data load: when results is finish /results2 start to load, for using it with $fetchState.pending
What will be the best way of doing it? I'm trying to adapt the answer from here but no success so far.
This kind of code should be working fine
<script>
export default {
async fetch() {
this.response = await axios
.get(`/api${this.$route.path}`, { // faster than this.$nuxt.context.route.path
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json',
},
})
.then((res) => { // ❌ this is useless because you're already using await above
const results = res.data.content.slice(0, 40)
return results()
})
.then((res) => { // ❌ this is useless because `slice` is NOT async
const results2 = res.data.content.slice(20, 40)
return results2()
})
},
}
</script>
Otherwise, I can also recommend a better approach overall, using async/await and not mixing it with .then at all, like this
<script>
export default {
async fetch() {
const response = await axios.get(
`/api${this.$route.path}`,
{
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json',
},
}
)
const results = response.data.content.slice(0, 40)
const results2 = results.data.content.slice(20, 40)
},
}
</script>
PS: note that some things are not async, hence do not need await (or .then at all).
It can even be shorten to the following
<script>
export default {
async fetch() {
const response = await this.$axios.$get( // 👈🏻 using the shortcut $get
`/api${this.$route.path}`,
{
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json',
},
}
)
const results = response.content.slice(0, 40) // 👈🏻 no need for `.data` here
const results2 = results.content.slice(20, 40) // 👈🏻 same here
},
}
</script>
Thanks to the shortcuts available with the axios module that you should be using anyway.
As of why you should use async/await, it's just more lisible and available everywhere already (IE is dead). Here is some more info about the whole async/await thing: https://javascript.info/async-await
Far prettier than this kind of syntax (also named callback hell)

When we call a api with post request it's showing [Error: Network Error]

Showing network error when i call the post api in react native and i am using axios.
Here is my code
export const walletRequest = async () => {
let config = {
headers: {
userID: 'BLOCALEVIG',
password: 'bloc#!2#22ev!g',
'Content-type': 'Application/json',
Accept: 'Application/json',
},
};
let data = {
mfsapiin: {
ReqService: 'WAL_API_WALLETSCREEN',
mobileNumber: '8639833477',
},
};
let url = `https://app.blocal.co.in:5959/mfmbs/mbintf/ina/processwalletapirequest.jsp?mfsapiin={
"ReqService":"WAL_API_WALLETSCREEN",
"mobileNumber":"8639833477"
}`;
const walletCheck = await axios
.post(url, data, config)
.then(resp => console.log('walletRequest.resp', resp))
.catch(error => console.log('walletRequest.err', error));
console.log('walletCheck', walletCheck);
};
Kindly tell me what is wrong in my code

axios cancellation caught inside of then() instead of catch()

I making a multi-upload file form.
Upon user cancellation, once the corresponding axios call get cancelled using cancel(), I having a weird behaviour. My axios call get caught inside the then() whereas it should be caught inside of catch(). The response inside of then() returns undefined.
I am having a hard time figuring if I did something wrong on the front-end part, I think my call is may be missing some headers or maybe it's on the backend part ?
const payload = { file, objectId: articleId, contentType: 'article' };
const source = axios.CancelToken.source();
// callback to execute at progression
const onUploadProgress = (event) => {
const percentage = Math.round((100 * event.loaded) / event.total);
this.handleFileUploadProgression(file, {
percentage,
status: 'pending',
cancelSource: source,
});
};
attachmentService
.create(payload, { onUploadProgress, cancelToken: source.token })
.then((response) => {
// cancelation response ends up here with a `undefined` response content
})
.catch((error) => {
console.log(error);
// canceled request do not reads as errors down here
if (axios.isCancel(error)) {
console.log('axios request cancelled', error);
}
});
the service itself is defined below
export const attachmentService = {
create(payload, requestOptions) {
// FormData cannot be decamelized inside an interceptor so it's done before, here.
const formData = new FormData();
Object.entries(payload).forEach(([key, value]) =>
formData.append(decamelize(key), value),
);
return api
.post(resource, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
...requestOptions,
})
.then((response) => {
console.log(response, 'cancelled request answered here as `undefined`');
return response.data;
})
.catch((error) => {
// not caught here (earlier)
return error.data;
});
},
};
cancellation is called upon a file object doing
file.cancelSource.cancel('Request was cancelled by the user');
As suggested by #estus-flask in a comment, the issue is that I was catching the error inside of the service (too early). Thank you!
export const articleService = {
create(payload, requestOptions) {
// FormData cannot be decamelized inside an interceptor so it's done before, here.
const formData = new FormData();
Object.entries(payload).forEach(([key, value]) =>
formData.append(decamelize(key), value),
);
return api.post(resource, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
...requestOptions,
});
},
};

Vuex store cannot be used inside axios handler

I have method being successfully called by a button in my Vue component:
methods: {
goTestMe() {
console.log(this.$store.state.lang+' 1')
let url = 'some api url'
let headers = { headers: { 'Content-Type': 'application/json' } }
this.$axios
.get(url, headers)
.then(function(response) {
console.log('here')
console.log(this.$store.state.lang+' 2')
})
The problem is that the output of this is:
en-us 1
here
When it should be:
en-us 1
here
en-us 2
Clearly, the reference to this.$store.state is failing in the then() handler of the axios call.
Why is this? How can I send data received by my axios request to the Vuex store?
when you add the callback in the normal function you can't access the global object so you need to change it to an arrow function
methods: {
goTestMe() {
console.log(this.$store.state.lang+' 1')
let url = 'some api url'
let headers = { headers: { 'Content-Type': 'application/json' } }
this.$axios
.get(url, headers)
.then((response) => { // change it to arrow function
console.log('here')
console.log(this.$store.state.lang+' 2')
})
}

How do I use a variable outside a function in react native?

I need to use that variable "let result" outside of this function. I need to use that variable inside of another function. How can I get it?
My code looks like this:
method: "GET",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Authorization': 'Bearer ' + this.state.clientToken,
},
})
.then((response) => response.json())
.then((responseJson) => {
let result= JSON.parse((responseJson.lstsurveyoncode))
let answer = JSON.parse(responseJson.lstsurveyoncode)[0].qoptions
console.log("responsejson",result[1].QUESTIONCODE)
console.log("answerrr",answer);
console.log("data length",result.length);
this.setState({
isLoading:false,
dataresponse:result,
// count:Object.keys(dataresponse).length
},function(){
});
You can create a global variable, and then update it inside your first function and in the second function you check if the variable is defined
let result;
function firstFunction(){
result = 'Your Json Result'
}
function secondFunction(){
if (!result) return;
// Here you can use your variable result
}
You should read about async-await and state managment in react-native.
For quick solution, you should mark your function with async modifier and await for result. Sample code below:
async function yourRequest() {
return new Promise((resolver, rejected) => {
// your async request
})
.then(response => response.json())
.then(responseJson => {
const result = JSON.parse(responseJson.lstsurveyoncode)
const answer = JSON.parse(responseJson.lstsurveyoncode)[0].qoptions
// ...
return {
result: result,
answer: answer,
}
})
}
async function handleResponse() {
const response = await yourRequest()
// and now, you can access to variables declared at `makeRequest` function
console.log(response.result)
console.log(response.answer)
}