React Native: setState doesn't work when calling try-catch function - react-native

I tried to call APP with this code imported from another file and it worked fine:
import FormData from 'FormData';
import AsyncStorage from '#react-native-community/async-storage';
let formData = new FormData();
formData.append('userId', '1'); // < this is what I want to change
formData.append('key', '***'); //my key
export function getScoreFromAPI () {
return fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body : formData
} )
.then((response) => {
return response.json()
})
.catch((error) => console.log("l'erreure est: " + error))
}
but now I want to change my userId from 1 to an constante from Asyncstorage, so I decide to change my code to this:
constructor(props) {
super(props)
this.state = { infos: [], userId: '' }
}
componentWillMount() {
this.getScoreFromAPI().then(data => {
this.setState({ infos: data })
});
console.log(this.state.infos);
AsyncStorage.getItem(USERID_STORED)
.then((data) => {
if (data) {
this.setState({userId:data})
}
});
}
async getScoreFromAPI() {
let formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //my key
try {
let response = await fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php',{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
let res = await response.json();
} catch(error) {
console.warn("errors are " + error);
}
};
with a try-catch function but when I call getScoreFromAPI() in ComponentWillMount() I can't setState with received data, I still have an empty array in info:[]
my questions:
how can I replace '1' in userId by a value in asyncstorage in the first file ?
if it isn't possible, what I have do to setState info: [] with my data reveived

I've simplified your code into a promise chain in which calling getScoreFromAPI will execute after getting the userId from AsyncStorage, then storing the response into the infos state, while returning null if there was an error, and logging the error to the console. The data was not previously returned from getScoreFromAPI, so the value would always become null. I have not tested this code, but this should give you a good base to work from:
import FormData from 'FormData';
import AsyncStorage from '#react-native-community/async-storage';
export default class Test {
constructor() {
this.state = {
infos: null,
userId: ''
};
}
componentDidMount() {
AsyncStorage.getItem(this.state.userId)
.then(userID => {
this.setState({ userId: userID || '' });
})
.then(() => {
return this.getScoreFromAPI();
})
.then(data => {
this.setState({ infos: data });
})
.catch(console.error);
}
getScoreFromAPI = () => {
const formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //my key
fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
.then(response => {
// use response data here
return response.json();
})
.catch(e => {
console.error(e);
return null;
});
};
}

You're doing your API call before fetching your value from AsyncStorage (I know this is async but it's not very readable if you do it that way).
getScoreFromAPI doesn't return anything, that's why your setState isn't working.
You don't need to use try and catch here, promises have their own error handling mechanism (the .catch() method).
I think callbacks are more readable and lead to less bugs than using .then() in code.
This is how I would do it:
constructor(props)
{
super(props);
this.state = { infos: [], userId: '' };
this.onSuccess = this.onSuccess.bind(this);
this.onFailure = this.onFailure.bind(this);
}
componentWillMount()
{
// Get userID from local storage, then call your API
AsyncStorage.getItem(YOUR_KEY)
.then(userID=> {
if (userID)
{
this.setState({ userId : userID }, () => {
this.getScoreFromAPI(this.onSuccess, this.onFailure);
});
}
});
}
onSuccess(data)
{
this.setState({
infos : data
});
}
onFailure(err)
{
console.warn('Error ' + err);
}
getScoreFromAPI(onSuccess, onFailure)
{
let formData = new FormData();
formData.append('userId', this.state.userId);
formData.append('key', '***'); //your key
fetch('https://www.globalfidelio.com/gfn_arcol/api/transaction.php', {
method : 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
})
.then(res => res.json())
.then(json => {
onSuccess(json);
})
.catch(err => {
onFailure(err);
});
}

It's finally done. I tried this and it worked. Thank you to all of you
this is what I have done:
...
const USERID_STORED = "userid_stored";
const GSM_STORED = "gsm_stored";
...
class ScoreList extends React.Component {
constructor(props) {
super(props)
this.state = { infos: [], userId: '', gsmStored: '', }
}
componentWillMount() {
AsyncStorage.getItem(USERID_STORED)
.then(userId => {
this.setState({ userId: userId});
this.getScoreFromAPI(this.state.userId).then(data => {
this.setState({ infos: data });
});
});
AsyncStorage.getItem(GSM_STORED)
.then(gsmStore => {
this.setState({ gsmStored: gsmStore});
});
}
getScoreFromAPI (userId) {
let formData = new FormData();
formData.append('userId', userId);
formData.append('key', '***');
return fetch('https://***',{
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body : formData
} )
.then((response) => {
return response.json()
})
.catch((error) => console.log("l'erreure est: " + error))
};

Related

Axios throws an "unauthorized" at me

This is strange because postman allows me to make a POST however react does not. the token is valid and when called, the token prints to console
export default class Create extends Component {
//url = 'http://127.0.0.1:5000/wtw/articles/'
constructor(props) {
super(props);
this.state = {
//author?
title: '',
description: '',
//image: ,
//token: null
};
}
handleCreate = async () => {
const { title, description, image } = this.state;
let token = await AsyncStorage.getItem('token');
axios
.post('http://127.0.0.1:5000/wtw/articles/', {
headers: {
Authorization: 'Token ' + token,
},
data: {
title: title,
description: description,
},
})
.then(async (Response) => {
console.log(Response);
})
.catch((err) => {
console.log();
console.log(err);
console.log(token);
});
};
}

React Native RNPicker select

i am using RNPicker Select in which i want dropdown items to get from api but i am getting empty dropdown with no values
following is my code
class Component extends Component {
constructor(props) {
super(props);
this.state = {
inqSourceList: [],
}
componentDidMount() {
this.fetchSource();
}
fetchSource = () => {
getInqSourceList('view=select', this, null)
}
<RNPickerSelect
items={this.state.inqSourceList}
name="source"
value={this.state.source ? this.state.source.id : null}
onValueChange={value => {
this.setState({
source:value,
});
}}
style={{marginBottom: 10}}
/>
and my api code is
export async function getModuleList (moduleName, params,error) {
let token = await AsyncStorage.getItem('token');
axios
.get(BASE_URL + moduleName + "?" + params, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: "Bearer " + token },
})
.then((res) => {
var bytes = CryptoJS.AES.decrypt(res.data.toString(), ENCDEC);
res.data = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
// success(res.data);
// console.log(res.data)
})
.catch(error);
}
in this i am getting values from backend when i use console.log(res.data) i get list of options..but the dropdown item is empty..
thanks
here is the function where inqSourceList is set
export function getInqSourceList(params, _this, next) {
getModuleList('settings/inquiry-source', params, data => {
_this.setState({inqSourceList: data.rows});
if (next) next(data);
});
}

How to use Async Storage Axios

Problem:
I have create react-native application.And there I am using AsyncStorage with axios in like this to handle my API calls.This is how that looks like.
import axios from "axios";
import { AsyncStorage } from "react-native";
// TODO: Replace this with actual JWT token from Keycloak
axios.defaults.headers.post["Content-Type"] = "application/json";
// Create axios instance for api calls
var instance = null;
export const setAuth = async () => {
const user = await AsyncStorage.getItem("jwt");
AsyncStorage.getItem("jwt").then(token => {
instance = axios.create({
baseURL: "",
timeout: 150000,
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json"
}
});
instance.interceptors.response.use(
function(response) {
return response;
},
async function(error) {
if (error.response.status) {
return error;
}
}
);
});
};
export const Get = (route, data) => {
instance || setAuth();
return instance.get(
route,
data == null ? { data: {} } : { data: JSON.stringify(data) }
);
};
export const Post = (route, data) => {
instance || setAuth();
return instance.post(route, JSON.stringify(data));
};
export const Put = (route, data) => {
debugger;
instance || setAuth();
return instance.put(route, JSON.stringify(data));
};
export const AddAdmin = (route, data) => {};
Becuase of the asynchronus property of AsyncStorage it is not creating the axios instanceinstance = axios.create({.The problem is with after this line .So can someone help me with this.I do not have any idea to find out what is wrong with this. Thank you.
You can give a try to this.
export const setAuth = async () => {
const token = await AsyncStorage.getItem('jwt');
instance = axios.create({
baseURL: '',
timeout: 150000,
headers: {
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json'
}
});
// remaining Code
};
export const Get = (route, data) => {
function getData(){
return instance.get(
route,
data == null ? { data: {} } : { data: JSON.stringify(data) }
)
}
if(instance) return getData()
return setAuth().then(getData)
}

How to upload image in react-native using axios?

I am trying to upload Image with Axios but getting: Request failed with status code 500.I don't have backend problem because I can upload image with postman and everything is fine.
This is my addDocument() in FileUpload.js.
addDocument(){
let { title, description, imgUri } = this.state;
console.log(this.state.imgUri);
const body = new FormData();
body.append('image', {
uri: imgUri,
type: 'image',
name : `${new Date().getTime()}.jpg`,
});
addDocument(title, description, body).then((response) => {
if (response.isSuccess == true) {
this.setState({ loading: false });
this.props.navigation.navigate('FileList',{isUpdate:'true'});
}
});
};
This is my addDocument() in document.service.js.
export const addDocument = async (title, description, imageFile) => {
const trekkerId = await AsyncStorage.getItem("trekker_id");
const model = {
profileDocumentId: '',
title: title,
description: description
}
console.log(model);
console.log(imageFile);
if (trekkerId) {
return axios({
method: 'post',
url: baseUrl + "/api/Document/Document",
data: {
file: imageFile,
model: model
},
headers: {
'profileId': trekkerId,
'Authorization': 'Bearer ' + await AsyncStorage.getItem("id_token"),
'Content-Type': 'multipart/form-data'
},
}).then((response) => {
// console.log(response);
return {
isSuccess: true
};
}).catch((error) => {
console.log(error);
return {
isSuccess: false,
}
});

React Native: API is not calling on 2nd time(fetch/axios)

I am creating react-native app using fetch method to get the data from API but when I am build the app(remove and install new app) that time it is calling API called but on 2nd time it is not.
I have also uses
componentDidMount, componentWillMount
but not work for me. following is my code:
export default test extends Component{
_isMounted = false;
constructor(props){
super(props);
this.state = {
showList:[]
}
}
componentDidMount() {
let currentComponent = this;
currentComponent._isMounted = true;
fetch(API_URL, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
}
}).then((response) => { return response.json()})
.then((responseJson) => {
console.warn("responseJson: ", responseJson);
if(currentComponent._isMounted){
currentComponent.setState({showList: responseJson.data});
}
})
.catch((error) => {
console.error(error);
});
}
componentWillUnmount(){
this._isMounted = false
}
}
I have add full code here. this is only called on first time, after that it will get only from cache(I think).Please help me.
Thanks
I'd look into the onEnter hook on your scene using react-native-router-flux.
Something like this should work:
class Test extends Component {
static onEnter() {
fetch(API_URL, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
}
}).then((response) => { return response.json()})
.then((responseJson) => {
console.warn("responseJson: ", responseJson)
if (currentComponent._isMounted) {
currentComponent.setState({ showList: responseJson.data })
}
})
.catch((error) => {
console.error(error)
})
}
}
(if you need to access this in the method, here is an idea)