Call a JSONP API with React - reactjs

I am trying to call an API that is given to me. First, I did not understand the question. The API given to me looks like 'test.com/a/b/c/d/d' and it also says: callback parameter name: 'jsonp'. I tried things like adding ?callback='jsonp' at the end of the API and other few things. I am trying to call this API and display the result. I am using React on CodeSandBox and I used the fetch() function to make this call. I keep getting error saying it failed. The API is correct but I just don't understand how I add that callback parameter. I have fetched other JSON based APIs before but this time I am doing something wrong, especially withe this JSONP things. Please help.
Edit** When I put that API in the browser, I do get actual data back. But it in this format /**/invalidCallbackFunctionName([ {DUMMY_DATA1}, {DUMMY_DATA2},.....]) So clearly the API works, it's just that the way I am calling it and the way JSONP works, I am missing something in the code.

Turns out I was not using the right package and the correct way. Here is what works:
import fetchJsonp from "fetch-jsonp";
fetchJsonp("https:/www.a.com/b/c/d", {
jsonpCallback: "jsonp"
})
.then((res) => res.json())
.then((data) => console.log(data));

Related

Is there any need of async/await in useEffect?

I was working on a project and was using firestore database from Firebase. I want to fetch data from the database once the page is reloaded. So the below code is working fine even without async await. But I have studied that we need async/await while API/DATA calls, please help me if I am wrong?
useEffect(() => {
db.collection('database_mcq').onSnapshot(snapshot => { setMcq(snapshot.docs.map(doc => doc.data())) })
}, [])
It's not only unnecessary, it's also forbidden - if you try to use an async function, React will throw an error, because the only thing that can be returned from an effect callback should be a function or nothing at all (and not a Promise).
Instead, use .then - if you're using standard Promises - or use whatever other method the API you're using provides for interacting with asynchrony. In your case, onSnapshot is fulfilling that role - there's no need to do anything else special.
Even in standard JavaScript, there's no requirement to ever use async/await, since it's just syntax sugar over .then.

How to POST form data in React without external API

I am working with Amazon's Mechanical Turk, trying to build an ExternalQuestion site which POSTs data back to AMT using a form-- this is the typical method of passing back answers from an ExternalQuestion, mandated by their API.
Very specifically, I am trying to do this in ReactJS, because it has simplified every other aspect of this project.
Is it possible to get React to POST form data without using an external back-end like Flask/python?
This is an important requirement because as far as I can tell from this information (and my own wasted time), using Flask/python will make the POST data look like it is coming from my server, rather than the Worker's browser, and will get rejected.
And yet, when I look through the React documentation on forms I don't even see a discussion of form methods, like GET and POST. I understand that React is going to want this handled by something like an onClick() function, but I can't see any way to do this in React without making the data look like it's coming from my server rather than Worker's browser.
Your best shot is to use the built in JavaScript Fetch API with the FormData interface.
For the body you can pass in the payload what you can generate with the FormData interface; MDN's documentation on it:
The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data".
Don't use XMLHttpRequest, fetch is the newer that is built on that.
A Generic example with fetch would look like the following:
const formData = new FormData();
formData.append('username', 'abc123');
formData.append('foo', 'bar);
fetch('https://example.com/foo/bar', {
method: 'POST',
body: formData
})
.then(response => response.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', JSON.stringify(response)))
This fetch call then can be called based on a user action like onClick.
Form post is just XHR POST with form-data or x-www-form-urlencoded body and get text/HTML returned. This can be done on React with Axios.
This answer show using Axios to send form-data -> https://stackoverflow.com/a/47630754/3849555

Dynamically filter out a JSON response in React

I'm trying to filter out a JSON response on the basis of an static array.
So for example, if the response is something like following
{
"Name":React,
"Version": 9.0,
"Level": Intermediate,
"Machine": Desktop,
"Release date": 2019-08-10
}
. This is stored in the state of the component.
And the array is, say
[ "Version", "Release date"]
and this is coming through props.
Now I want to filter the json data using this array. So, that means if we use the given example, I should only be able to display the fields version and release date!
Is there a way to do it?
Then how is it proper to iterate through each of them and exactly where? Like should it be filtered within the componentDidMount function or we need to define another function for it?
I'm a newbie working on React and JSX.
I'm not sure i understood exactly your objective, but let's try it.
First, you want to set the state with the response.
So you must set a state response: {} in the constructor. Have you done that?
If so, great!
Now, when you get the response, either using axios.get() or fetch(), you set the response to the state.
axios
.get(url)
.then(res => { this.setState({ response: res }); }) //sets JSON object to state
.catch(e => console.log(e)); //return a error to the console if it fails
(PS: if you use the react fetch() function, you first need to convert the response to JSON using .json(); before using setState)
But I don't understand your array question.
You want to append to an array the values of ReleaseDate and Version?
Or simply replace its data?
Perhaps you would want to crate an array of objects, where each object has a version and release date field. Or maybe even append the whole response to this array (sorta like keeping a history of previous responses) and accessing the version and date fields directly.
Could you clarify?
Also, just a tip:
You asked if you should iterate in componentDidMount or another function. I would recommend you creating a function like readResponse and call it in componentDidMount(), except when you're absolutely sure that it won't need to be called again. Let's say you will make more than 1 request at this page, you'll need to call it more than once.
AFTER QUESTION EDIT:
#VarnikaChaturvedi Sorry for the late response. I guess i understood your question.
Here's what we can do:
Let's use the same code i mentioned before, but on a little different:
axios
.get(url)
.then(res => {
this.setState({ response: res.data });
myArray.push({
"Version": res.data.get("Version"),
"Release date": res.data.get("Release date")
});
})
.catch(e => console.log(e));
// what is supposed to happen is add a object containing version
// and release date to a already defined array named myArray
PS: i'm typing this from memory, so there probably is a syntax error or something silly, so read the errors if there is any.

Passing the response of one API call to another API as a parameter in same file in React

I am learing react and I am stuck in my project. I have two APIs. I fetch cookie from one API and I want to use that cookie as a parameter in another API and both API is called in the same file i.e index.js. How to do this?
You are asking about promises. Based on your problem, you already know that API calls are asynchronous. You control async functions by "forcing" them to wait and return their response before proceeding to the next line of code. A promise is an object you use as a wrapper for your API that does this for you. Here's a basic example:
const apiPromise = () => new Promise((resolve, reject)=> {
const apiData = myApiCallForCookies()
resolve(apiData)
})
apiPromise().then(cookies => nextApiCall(cookies))
If you are confused by the syntax with things like .then, MDN docs are your friend.

Catch API and 401 errors globally in React's router

I use react + react-router + redux. I would like to create a global thing for handling all the errors thrown in the app. Is it possible to catch also API call errors and 401 statuses?
I thoung about something like this in Root.jsx:
window.addEventListener("error", (e) => {});
It works for critical errors which I can log. But what if I want to serve some API errors?
For example: I want to save some grid data, but server thrown an error that 3 of 10 given rows weren't saved (I know it's a common problem and it should be resolved using transactions, but I use Mongo here :P). Now I want to show a simple dialog for a user which displays error message and 3 rows that weren't saved. What if I don't have permissions and the server throws 401 status code? Probably I would like to redirect user to index or login page.
This is some hipothetical example, because I want to simplify the thing I'm currently implementing.
I'm new in React, so I don't know the solutions for now, but if I programmed same thing in Angular, I would use Angular's HTTP Interceptors to solve my problem. I guess I need something similar here (or maybe it's some common solution for this?).
[EDIT]
Hmm. It seems I have found something that solves my problem: fetch-intercept
Anyway, do you know other solutions?
I'm assuming you're using ajax calls to access your API;
I would create a simple ajax wrapper that looks something like this;
AjaxWrapper = function(options){
return $.ajax($.extend({}, options, {
error: function (jqXHR, textStatus, errorThrown){
if(jqXHR.status === 401){
browserHistory.push('/unauthorized_route_handler');
}
options.error(jqXHR, textStatus, errorThrown);
}
}))
}
Then you can simply use this wrapper to call your api, passing in an options object as you normally would to $.ajax. Update the section within the jqXHR === 401 as needed, or add handlers for 403 & 500 as well.

Resources