ReactJS several fetch requests with promise - javascript

I need several fetch requests in my application to fetch data from different collections. Therefore, I wanted to use promises to make it work.
I have never used promises and despite my research on stackoverflow and other websites, I was not able to make it work.
Essentially, I need two fetch requests and I want to save the result of these requests to 2 different states.
This is what I have as of right now:
getFormData () {
fetch('/formdata', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}})
.then(res => res.json())
}
getIcons () {
fetch('/icons', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}})
.then(res => res.json())
}
getData () {
return Promise.all([this.getFormData(), this.getIcons()])
}
componentDidMount () {
this.getData()
.then(([formdata, icons]) => {
console.log(form + " " + icons);
})
.catch(err => console.log('There was an error:' + err))
}
But this did not work.
I also tried putting the promise in my componentDidMount() lifecycle method, like so:
componentDidMount () {
return Promise.all([this.getFormData(), this.getIcons()])
.then(([formdata, icons]) => {
console.log(formdata + " " + icons);
})
.catch(err => console.log('There was an error:' + err))
}
But this didn't work eiter.
I would like to save the data from /formdata to a state with the same name and the same goes for icons, but in the console it simply returns undefined undefined, instead of the formdata and the icons.
Where am I making a mistake in my code? How would I fix it?

You need to return Promise object from your methods. As of now you are not returning anything, so it's implicit undefined.
Try this:
getFormData () {
return fetch('/formdata', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}})
.then(res => res.json())
}
getIcons () {
return fetch('/icons', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}})
.then(res => res.json())
}

Just adding to #dfsq's answer, after returning the promises you can update the state within each function:
constructor(props) {
super(props);
this.state = {
formData = {},
icons: {}
}
}
getFormData () {
return fetch('/formdata', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}})
.then(res => res.json(
this.setState({ formData: res.json })
))
}
getIcons () {
return fetch('/icons', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}})
.then(res => res.json(
this.setState({ icons: res.json })
))
}

Related

How to update state with react js with componentDidUpdate and setState?

How to update the data with react js eg a user writes a comment how to make this messages show up to all other users?
I used setState in componentDidUpdate with a stop condition but it doesn't work.
If i don't make a condition, it work correctely but with infinite loop.
componentDidUpdate(prevProps, prevState) {
console.log("1" + prevState.changeRepComm.toString())
console.log("2" + this.state.changeRepComm.toString())
if (prevState.changeRepComm !== this.state.changeRepComm ) {
if (this.updateTimer) return;
this.updateTimer = setTimeout(() => {
//lister response comments
fetch('/api/ReponseCommentaire/listerReponseCommentaire', {
method: "GET",
headers: {
'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(response => {
console.log('Ajouter response:' + JSON.stringify(response))
this.setState({ ...this.state, reponseCommentaires: response });
})
.catch((err) => {
console.log('fetch failed => ', err);
})
}, 1000);
} }
If your looking to update every second, you can initialize a timer when component mounts.
componentDidMount(prevProps, prevState) {
if (this.updateTimer) { return; }
this.updateTimer = setInterval(() => {
fetch('/api/ReponseCommentaire/listerReponseCommentaire', {
method: "GET",
headers: {
'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(response => {
this.setState({
...this.state,
reponseCommentaires: response,
});
})
.catch((err) => console.log('fetch failed => ', err) )
}, 1000);
}

JavaScript Fetching Multiple Requests In An Order

I am trying to fetch multiple requests in an order in React. There are 3 requests,
first one gathering encoded information from backend
get token from authentication server
use api with the token.
All of them must be in order. But I am having difficulties because of async fetch function. I can't reach fetch's response outside of .then() block.
To solve it, I used await / async. But it caused another problem. My 3 requests must be in a sequencial order. When I use async, order gets broken.
Here is the code.
class App extends Component {
constructor() {
super();
this.state = { code: '', encoded: '', access_token: '', refresh_token: '' };
}
getCarDetails() {
const carId = '2F3A228F6F66AEA580'
var query = 'https://api.mercedes-benz.com/experimental/connectedvehicle/v1/vehicles/'.concat(carId).concat('/doors')
fetch(query, {
method: 'GET',
headers: {
'Authorization': 'Bearer '.concat(this.state.access_token),
'accept': 'application/json'
}
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err));
}
getToken() {
var post_data = {
grant_type: 'authorization_code',
code: this.state.code,
redirect_uri: 'http://localhost'
}
fetch('https://api.secure.mercedes-benz.com/oidc10/auth/oauth/v2/token', {
method: 'POST',
headers: new Headers({
'Authorization': 'Basic '.concat(this.state.encoded),
'Content-Type': 'application/x-www-form-urlencoded'
}),
body: queryString.stringify(post_data)
})
.then(res => res.json())
.then(data => this.setState({ access_token: data.access_token, refresh_token: data.refresh_token }))
.catch(err => console.log(err));
}
getEncodedClientIdAndClientSecret() {
if (this.state.code != null) {
fetch('http://localhost:8000/encodeClientIdAndSecret', {
method: 'POST'
})
.then(res => res.json())
.then(data => this.setState({ encoded: data.encoded }))
.catch(err => console.log(err));
}
}
componentDidMount() {
const values = queryString.parse(this.props.location.search)
this.setState({ code: values.code })
console.log(this.state)
this.getEncodedClientIdAndClientSecret();
console.log(this.state) //this state is empty
//this.getToken();
//this.getCarDetails();
}
AWAIT / ASYNC
async getEncodedClientIdAndClientSecret() {
if (this.state.code != null) {
const response = await fetch('http://localhost:8000/encodeClientIdAndSecret', {
method: 'POST'
})
const data = await response.json();
console.log(data)
}
}
If I put await / async, I am having sequence problem between 3 requests.
in order to use async await on methods like
await getEncodedClientIdAndClientSecret();
await getToken();
you need to first return a promise from those functions like:
getToken() {
var post_data = {
grant_type: 'authorization_code',
code: this.state.code,
redirect_uri: 'http://localhost'
}
return fetch('https://api.secure.mercedes-benz.com/oidc10/auth/oauth/v2/token', {
method: 'POST',
headers: new Headers({
'Authorization': 'Basic '.concat(this.state.encoded),
'Content-Type': 'application/x-www-form-urlencoded'
}),
body: queryString.stringify(post_data)
})
.then(res => res.json())
.then(data => this.setState({ access_token: data.access_token, refresh_token: data.refresh_token }))
.catch(err => console.log(err));
}
so it can wait for the promise to finish, othewise they will run in parallel and finish in random order.

get the return value of an arrow function using React

I have this arrow function:
saveNewPermissions = (newGroupPermissions, groupName) => {
fetch(this.baseUrl + "/addPermission/group/" + groupName, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify({
permissions: newGroupPermissions
})
}).then(response => response.json())
.then(json => {
console.log(JSON.stringify(json))
return json;
});
}
That function above is on the Service file, and on my component class i want to get the json that the function returns:
this.Service.save(newList, groupName)
I tried to do this but it didnt work:
this.uaaService.saveNewPermissions(newList, groupName).then(response=>{
console.log(response)
})
First of, you would want to return the Promise from the arrow function
saveNewPermissions = (newGroupPermissions, groupName) => {
return fetch(...) // returns a Promise object
}
then if you expect newList to be an array, you want to do:
this.uaaService.saveNewPermissions(newGroupPermissions, groupName).then((newListJSON) => {
this.Service.save(newListJSON, groupName);
})

React Native "fetch" returning server response without the information

I am using react native to create an application to act as a website that currently exists (with a user interface that works on a phone). i am using the "fetch" method to send a Http POST request to get information from a web server. The web server sends a response but it doesn't include the response message:
I apologies that is an image but the debugger is not working for me.
The code used to send the request:
HttpRequest = (RequestURL, callback) => {
var AdminLoginBindingModel = {
usr: this.state.username,
pwd: this.state.password,
}
fetch(RequestURL,
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then((res) => {
callback(res);
})
.catch((error) => {
this.setState({Response: "Error: " + error});
})
}
The callback function in the parameters is just a function to change the state variable to display the information on the screen
ValidateResponse(response){
this.setState({Response: "Result: " + JSON.stringify(response),
displayMessage: "Success"});
console.log(JSON.stringify(response));
}
The Request being sent is "https://mibase-test.mibase.com.au/members/api/startSession.php?usr=&pwd="
The server responds with a json object regardless of a correct login or not
Edit:
Changing the response to
.then((res) => {
callback(res.json());
})
Result:
To get object from fetch response, you have to call res.json like following:
fetch(RequestURL, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then(res => res.json()) // HERE
.then(obj => callback(obj))
But it occurs an error because response body itself is invalid json format. It contains some HTML tags:
{"member": {"username":"","password":"","key":"***","status":"No"}}<br><br>Username: <br>Key: ***
Please check the inplementation of server.
EDIT: full code here
const fetch = require("node-fetch")
HttpRequest = (RequestURL, callback) => {
const AdminLoginBindingModel = { usr: "foo", pwd: "bar" }
fetch(RequestURL, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then(res => res.json())
.then(obj => callback(obj))
.catch(error => console.log(error))
}
const ValidateResponse = response => console.log(JSON.stringify(response))
URL = 'https://mibase-test.mibase.com.au/members/api/startSession.php?usr=&pwd='
HttpRequest(URL, ValidateResponse)
response doesn't contain received data directly. It provides interface methods to retrieve it. For example use response.json() to parse response text as JSON. It will return promise that resolves to the parsed object. You won't need to call JSON.parse on it:
fetch(RequestURL,
{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(AdminLoginBindingModel)
})
.then((res) => {
return res.json();
}).then((obj) => {
console.log(obj);
});
Check https://developer.mozilla.org/en-US/docs/Web/API/Response and https://facebook.github.io/react-native/docs/network.html for more information.

fetch data error with react native

I used two classes
I call the second class as below
let s = new SearchExtend();
output = s.fetchData(search)
alert(output)
The second function:
fetchData = (search) => {
fetch('http://example.com/search.php' , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
// Getting the search.
search: search
})
}).then((response) => response.json())
.then((responseJson) => {
return responseJson;
})
.catch((error) => {
console.error(error);
});
}
But i get in "alert" undefined
When I use this.setState instead of return, I get the following error:
warning setstate(...) can only update a mounted or mounting component
You are getting undefined because you are using promises. Initially it returns undefined and once promise is resolved you get the actually data.
A better way to handle this would be to return the promise and resolve it externally as follows:-
const fetchApi = () => {
return fetch("https://swapi.co/api/people" , {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then((response) => {
return response.json();
})
.then((responseJson) => {
return responseJson;
})
.catch((error) => {
console.error(JSON.stringify(error));
});
}
fetchApi()
.then((data) => {
console.log("data", data);
})

Categories

Resources