Undefined data after responseJson is entered into state [] in ReactJS - json

I have a problem here, namely when I do the Post API and add console.log (responseJson) the data appears and its contents are (app_uid and app_number). But when I enter the API data into the dataApp [] state and I try console.log (this.state.dataApp), no data appears.
Here is a piece of script from its post API function:
onTask = (pro, tas) => {
fetch('https://bpm.***********.or.id/api/1.0/**********/cases/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip, deflate',
'Authorization': 'Bearer ' + this.state.token,
},
body: JSON.stringify({
'pro_uid': pro,
'tas_uid': tas,
}),
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson); //here the data appears
this.setState({
dataApp: responseJson,
});
console.log(this.state.dataApp); //but here does not appear any data
});
Hopefully I can find a solution here, thank you very much.

this.setState is an asynchronous function.
Meaning - in your example, that you won't see its result on the next line where you console log it, because it is not yet done.
Try the following:
this.setState({
dataApp: responseJson,
}, () => console.log(this.state.dataApp)); // console.log inside a callback
To understand why it works inside a callback, and not in the next line, take a look at this MDN Article and this React Documentation

setState() is an async call in React. So you won't likely get the updated state value in the next line. You need to use the callback handler to get the updated value.
onTask = (pro, tas) => {
//Code you need to add
var that = this;
fetch('https://bpm.***********.or.id/api/1.0/**********/cases/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip, deflate',
'Authorization': 'Bearer ' + this.state.token,
},
body: JSON.stringify({
'pro_uid': pro,
'tas_uid': tas,
}),
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson); //here the data appears
that.setState({
dataApp: responseJson,
}, () => {
console.log("dataApp: ", that.state.dataApp);
});
});

Related

Json-sever GET requests keep firing

I've set up a json-server locally on my machine to use as a mock API for an app that I'm creating. I'm running the server on Port 3004 whilst my app is running on Port 3000. The app functions as expected; however, on inspecting the terminal on which the server is running, I noticed that GET requests are continuously being called every millisecond - see image below:
Is this normal behaviour? I would expect the GET request to be called just once, as per my code below. The GET request is part of a React app and is called inside of useEffect.
useEffect(() => {
fetch('http://localhost:3004/invoices',
{
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
}
)
.then(function(response){
return response.json();
})
.then(function(myJson){
setData(myJson);
})
.catch((error) => {
console.error("Error:", error);
});
});
You need to add a dependency to your useEffect, for example, if you want it to fire only on the first render, you would write it like
useEffect(() => {
fetch('http://localhost:3004/invoices',
{
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
}
)
.then(function(response){
return response.json();
})
.then(function(myJson){
setData(myJson);
})
.catch((error) => {
console.error("Error:", error);
});
},[]);
More likely, you will want the effect to fire off when something changes, in that case, add the dependecy to the square brackets like so...
useEffect(() => {
fetch('http://localhost:3004/invoices',
{
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
}
)
.then(function(response){
return response.json();
})
.then(function(myJson){
setData(myJson);
})
.catch((error) => {
console.error("Error:", error);
});
},[someState]);

how to fetch api(POST) with header in react native app

I am trying to put three params in my post request to particular api but i didn't get the response as i expected. API works fine in my Postman but i am not sure about my fetching method in my react native app i am new to this so i don't know how to put headers in my api request i followed some docs but didn't get much please have a look and answer my question.
constructor (props) {
super (props)
this.state = {
detail: ''
}
}
ComponentDidMount(){
var data = new FormData();
data.append('mobile_number','8615351655')
data.append('mobile_country_code','+21')
data.append('rec_name','Shantanu Talwaar')
}
fetchData = async() => {
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
//this what's exactly look in my postman
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb;
},
body: this.data
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson.detail)
}).catch((error) => {
alert('error')})}
render() {
return (
<View style = {styles.container}>
<Button onPress = {this.fetchData} title = "fetch"/>
<Text style={styles.text}>Fetched data displays below</Text>
<Text style={styles.text}>{this.state.detail}</Text>
</View>
)
}
}
This is the result i am having right now in my alert box: "Authentication credentials were not provided."
There is a ' missing after your token.
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb;
And as it is a JSON Object you should remove the semi-colon
So, the final code will be
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
There is also another problem. The data declaration is not accessible from the fetch function. So you should do something like this.
fetchData = async() => {
var data = new FormData();
data.append('mobile_number','8615351655')
data.append('mobile_country_code','+21')
data.append('rec_name','Shantanu Talwaar')
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
//this what's exactly look in my postman
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
},
body: data
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson.detail)
}).catch((error) => {
alert('error')
})
}
i think you can use "x-access-token" as header name for authentication token and place Content-Type too.
fetchData = () => {
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
'Content-Type': "application/json",
'x-access-token': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
},
body: this.data
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson.detail)
}).catch((error) => {
alert('error')})
}

React Native - Second API Call is not returning value

My problem is that my code is returning an undefined value because of my second API Call:
render(){
const result_postid = this.state.data_one.map(function(val) {
return val.postid;
}).join(',');
const result_spaceid = this.state.data_one.map(function(vall) {
return vall.spaceid;
}).join(',');
//These two will receive values.
const result_image = this.state.data_two.map(function(valll) {
return valll.image;
}).join(',');
//This last one somehow will not receive value
}
Here I am fetching two APIs in the same componentDidMount:
componentDidMount(){
//First API Call
fetch(`http://www.exmaple.com/React/data.php`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
data_one: responseJson,
},function() {
});
}).catch((error) => {
console.error(error);
});
// Second API Call
fetch(`http://www.example.com/React/image_data.php`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
data_two: responseJson,
},function() {
});
}).catch((error) => {
console.error(error);
});
}
To confirm that it wasn't just a data response issue, I deleted the first to const (result_postid) and (result_spaceid) and the error was gone (TypeError: undefined is not a function (evaluating 'this.state.data_two.map(function(valll){return valll.image}')). The data showed successfully, but I need all 3 const to return the value. Is there a way to return all values for all 3 const?
The API calls are asynchronous, when you use the values in the render function some of them do not exist until all the calls return. You should have an initial state in the constructor
constructor(props) {
super(props);
this.state = {
data_one: [],
data_two: []
}
}
That way the values are not undefined. When the API returns the value, then the setState will trigger the render again.
Also, why do you have an empty function in the setState in the callbacks?
It should be something like
this.setState({
data_two: responseJson,
});
A couple of recommendations:
Use camelCase for variable naming, _ is not an usual standard in JS
Move the API calls to a different file, that will help you keep the component more organized. Then from componentDidMount you just call the function to make the request.

Unhandled promise rejection Error: Cannot read property 'json' of undefined

answers.map((answer, index) => {
answer_text = answer.answer_text;
id = answer.id;
return fetch(BASE_URL + url, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Token token=' + token
},
body: JSON.stringify({
question: {
answers_attributes: {
'0': {
answer_text: answer_text,
id: id
}
}
}
})
});
})
I used map function so that on every map it should go to JSON.stringify and assign the values. But I got error "Unhandled promise rejection TypeError: Cannot read property 'json' of undefined". please suggest me any solution.
Thanks in advance.
Here you are creating an array of fetch promises, we need more info about how you handle these promises after that, i suppose you're trying somewhere to get a response from these promises using .then(res => res.json()) but your server response is not in json format.
To handle a fetch promise rejection you need to do this:
fetch(smth)
.catch(error => //handle the error e.g. console.log(error))
To see if there's something wrong in your request json body you can log it server side or log it before sending, you can also log the server response, try this to identify what's wrong:
answers.map((answer, index) => {
answer_text = answer.answer_text;
id = answer.id;
const body = JSON.stringify({
question: {
answers_attributes: {
'0': {
answer_text: answer_text,
id: id
} }
}
})
console.log('Json body request :', body);
return fetch(BASE_URL + url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Token token=' + token
},
body
}).then(res => {
console.log('server response :', res);
return res;
}).catch(err => console.log('Fetch error :', err));
})
I recommend using an app like Postman to test the responses from your api server (easier & faster to debug request/responses from an API)
Edit: I also think you want to do a POST request instead of PUT.

React Native - Parsing error from JSON Response

Here is my code.
I am calling the following function to get state list.
callGetStatesApi()
{
callGetApi(GLOBAL.BASE_URL + GLOBAL.Get_States)
.then((response) => {
// Continue your code here...
stateArray = result.data
Alert.alert('Alert!', stateArray)
});
}
Here is common callGetApi function for getting response from GET Api.
export function callGetApi(urlStr, params) {
return fetch(urlStr, {
method: "GET",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(params)
})
.then((response) => response.json())
.then((responseData) => {
result = responseData
})
.catch((error) => {
console.error(error);
Alert.alert('Alert Title failure' + JSON.stringify(error))
});
}
I am getting the following error.
Alert only show the string , but your case "stateArray" is complex object (array,structure..)
So use stateArray.toString() or JSON.stringify(stateArray),
Or
Try the below method and let me know,
fetch(GLOBAL.BASE_URL + GLOBAL.Get_States, {
method: 'get',
headers: { 'Accept': 'application/json','Content-Type': 'application/json',}
}).then((response) => response.json())
.then((responseData) => {
console.log(responseData) // this is the response from the server
// Continue your code here...
stateArray = result.data
Alert.alert('Alert!', stateArray)
}).catch((error) => {
console.log('Error');
});