How to retrieve response data from a fetch post request? - fetch

I'm trying to display the data comes back from a server, I can see the data coming back from the server I'm hitting when I look at network tab in Chrome's developer window.
How can I get access to it in my code below?
The handleClick method is called when a button is clicked.
Thanks!
let data;
async function handleClick() {
const url = "http://127.0.0.1:8000/parse"
data = await fetch(url, {
mode: 'no-cors',
method: "POST",
headers: { 'Content-type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
locale: "en_GB",
text: "Test Message"
})
})
.then(x => x.text())
console.log(data)
}

// Capture in the promise return section
.then(x => {
// Catch the data through the propertiesName.
// Here properties means your post request's variable name which you are given.
console.log(x.propertiesName);
});

Related

Post request to normal route, not using API middleware

Below my pages directory i have a few routes (for example "/product/details").
I'm using getServerSideProps() to have the page render server side.
How can i send a POST request containing data in the body to this page directly?
The idea would be that i can do something like this:
export async function getServerSideProps(postData) {
return {
props: {postData.body},
}
}
I've tried console logging "postData". I can see that the post request headers are being sent, but the request body is missing.
Thanks
Edit:
I'm doing the posting using Postman, and i'm sending a raw body of type JSON containing a single key:value. But as i said, the page doesn't seem to receive the posted data.
Here is a code snippet for how i'm sending a post request to a route using puppeteer:
const page = await puppeteerConnection.newPage();
await page.setRequestInterception(true);
await page.once('request', (request) => {
let data = {
'method': 'POST',
'postData': JSON.stringify(jsonData),
'headers': {
...request.headers(),
'Content-Type': 'application/json'
},
};
request.continue(data);
page.setRequestInterception(false);
});
await page.goto('pathToNextJSRoute');
getServerSideProps() accepts a context parameter (which you've named postData in your example) and one of the keys in that object (req) contains the request body you're looking for. It arrives as a readable stream of byte data, though, so you'll need to convert it first:
const streamToString = async (stream) => {
if (stream) {
const chunks = [];
for await (const chunk of stream) {
chunks.push(Buffer.from(chunk));
}
return Buffer.concat(chunks).toString("utf-8");
}
return null;
};
export async function getServerSideProps(context) {
let data = null;
if (context.req.method === "POST") {
const body = await streamToString(context.req);
data = JSON.parse(body);
}
console.log(data);
return {
props: { data },
};
}

Where is fetch getting it's endpoint value from?

I have the following code, I am using React:
// post-post
const queryDatabase = (obj, endpoint) => {
console.log(obj);
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(obj)
};
console.log(endpoint);
fetch(endpoint, requestOptions)
.then(data => {return Promise.resolve(data)}
);
}
export {queryDatabase};
For some reason console.log(endpoint) prints the endpoint that I am passing in, e.g. "/users", "/profile" etc. However, fetch is trying to send to http://localhost:3000/users so when I try to manually pass in an endpoint I get an error about trying to post to http://localhost/http://localhost/users.
Where is fetch getting this default http://localhost:3000 value?
It's only doing this for POST requests.
The only environment variables are the following:
REACT_APP_AUTH0_REDIRECT_URI=http://localhost:3000
REACT_API_SERVER_URL=http://api.localhost
PORT=3000
I also have some other environment variables for Auth0, is Auth0 doing this? I've removed these variables for testing and still nothing.
The answer is to use the Request object and pass that through to fetch:
const requestOptions = new Request(serverUrl + endpoint, {
method: 'POST',
body: JSON.stringify(obj),
headers: new Headers({
'Content-Type': 'application/json'
})
});
Why bother... use axios or something else, fetch sucks.
EDIT:
Apparently not a problem with fetch. Whatever the case this is the fix.

google places api returns a string, how do I parse to JSON object?

In a small webshop that I am trying to setup, I need to update the opening hours in the background with firebase functions and google place details when a user creates a shoppingcart.
I can succesfully sent a GET request with POSTMAN to retrieve the opening hours of a shop using the following instructions:
https://developers.google.com/places/web-service/details
But I cannot access the response from the GET request as I usually do with JSON responses.
I tried also:response.result.opening_hours.json()
Can someone tell me what I am doing wrong?
export const mapGooglePlaces = functions.database
.ref('/shopping-carts/{shoppingCartId}/shippingManner')
.onWrite(event => {
const shippingManner = event.data.val();
const optionsAPI = {
method: 'GET',
uri: 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=YOUR_API_KEY',
};
return request(optionsAPI)
.then(response => {
const openingHours = response.result.opening_hours;
console.log(openingHours);
return;
})
.catch(function (err) {
console.log(err);
});
});
The response is not a JSON object. It is JSON formatted text and must be parsed to create an object. Modify the code as follows:
return request(optionsAPI)
.then(response => {
const responseObject = JSON.parse(response);
const openingHours = responseObject.result.opening_hours;
console.log(openingHours);
return;
})
.catch(function (err) {
console.log(err);
});
Also, before using the opening_hours or any other property of result, you should test responseObject.status === 'OK' to confirm that a place was found and at least one result was returned.

Redux form: fields not updated after first submit

I'm using redux-form with mongodb and I can't manage to make a second submission works due to the following error:
{"message":"No matching document found for id \"590b02068012fb3f83e5da9d\"","name":"VersionError"}
which is due to the fact that the version of the document is not updated in the form.
The first submission works and data is upated; I get a new object from the REST endpoint and I set it into the state. Anyway the version value submitted by the form is not updated and this causes the error. Do I need to trigger this update manually on onSubmitSuccess callback?
Here's my form:
RegionEdit = reduxForm({
form: 'RegionEdit', // a unique identifier for this form
})(RegionEdit);
const mapStateToProps = createStructuredSelector({
initialValues: makeSelectRegion(),
});
function mapDispatchToProps(dispatch) {
return {
dispatch,
};
}
export default connect(mapStateToProps, mapDispatchToProps)(RegionEdit);
This is how I submit the form:
submit(values) {
return new Promise((resolve, reject) => {
this.props.dispatch(saveRegion({ values, resolve, reject }));
});
}
the following saga is executed:
export function* saveRegion(data) {
const payload = data.payload.values.toJS();
const reject = data.payload.reject;
const resolve = data.payload.resolve;
const requestURL = `${ENDPOINT_URL}/${payload._id}`;
try {
const region = yield call(request, requestURL, {
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
method: 'PUT' });
yield put(regionSaved(region));
resolve(region);
} catch (err) {
yield put(regionSavingError(err));
reject(err);
}
}
and regionSaved triggers SAVE_REGION_SUCCESS action which causes this code to execute in the reducer:
case SAVE_REGION_SUCCESS:
return state
.set('region', fromJS(action.region));
I attach some screenshot
state field version is updated from 5 to 6 after the first successful submission1
the payload of the second call has still old/initial version number (5)2
I found the issue, the problem was in the reduxForm instantiation, I just needed to pass property enableReinitialize set to true
RegionEdit = reduxForm({
enableReinitialize: true,
form: 'RegionEdit', // a unique identifier for this form
})(RegionEdit);

Sending data as key-value pair using fetch polyfill in react-native

The following code is to make HTTP POST request with fetch polyfill:
fetch(url, {
method: 'post',
body: JSON.stringify({
token: this.state.token,
}),
})
.then((response) => response.json())
.then((responseData) => {
console.log(responseData);
})
.done();
This request sends data as a stringified JSON obj. Is there a way to send data as key-value pair similar to requests? post(URL, data=payload) in python.
Sounds like you want the same format as a querystring, so import/require a package like https://www.npmjs.com/package/query-string which doesn't appear to depend on any browser features and has a stringify method:
queryString.stringify({
foo: 'bar',
nested: JSON.stringify({
unicorn: 'cake',
}),
});
//=> foo=bar&nested=%7B%22unicorn%22%3A%22cake%22%7D
Alternatively you could just use the relevant part of its source code, though this would still be subject to its license:
function toQueryString(obj) {
return obj
? Object.keys(obj)
.sort()
.map(function (key) {
var val = obj[key];
if (Array.isArray(val)) {
return val
.sort()
.map(function (val2) {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
})
.join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
})
.join('&')
: '';
}
You can then use the return value in your body parameter in fetch:
fetch(url, {
method: 'post',
body: toQueryString({ token: this.state.token }),
});
Sure. Look at the fetch documentation in github: https://github.com/github/fetch
It uses document/DOM web, but it should be the same for react-native case - just use FormData object and append all the form fields to send.
var form = document.querySelector('form')
fetch('/users', {
method: 'post',
body: new FormData(form)
})
And:
var input = document.querySelector('input[type="file"]')
var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')
fetch('/avatars', {
method: 'post',
body: data
})

Resources