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
Related
I want to use Mailchimp API in my website so users can enter their email in a field and subscribe to a newsletter. I do not want to use any libraries.
I created a simple form for now with an email field and subscribe button for testing purposes and tried to achieve my goal with XMLHttpRequest. However it does not work, and I am not sure whats wrong or if I need another approach? Is my code structure for the API request correct?
I created a Codesandbox with the code.
If needed I can paste it also here.
It's a back end only API.
You're not supposed to ship this API key with your JavaScript application. It's intended for back end use only, where you can keep the key private.
Probably the issue described in no more detail than "it does not work", is because Mailchimp will block the request if you try to use the key from a browser. Their documentation describes in detail.
Because of the potential security risks associated with exposing account API keys, Mailchimp does not support client-side implementation of our API using CORS requests or including API keys in mobile apps.
If you still want to use the API for this, you'll have to set up your own back end service which receives the data from the front end of your site and forwards it to Mailchimp.
For example, if your website uses PHP, you could preserve your form's JS code, but point it to your own custom endpoint / PHP file instead.
Mailchimp has a PHP client library you could use to make crafting the HTTP request more robust and less verbose. But you could also do it "manually" if you also don't want to install a PHP library.
// form-submission.php
function read_key() {
// Could also come from other source, like environment variables.
// As long as it's in a safe place and can't be leaked.
return file_get_contents(SECRET_KEY_LOCATION);
}
$apiKey = read_key();
require_once('/path/to/MailchimpMarketing/vendor/autoload.php');
$mailchimp = new MailchimpMarketing\ApiClient();
$mailchimp->setConfig([
'apiKey' => $api_key,
'server' => 'YOUR_SERVER_PREFIX'
]);
$response = $mailchimp->lists->addListMember( /* ... form data */);
print_r($response);
Depending on your use case you may need to use one of the many other API endpoints.
The issue is the onSubmit() callback on your "form" element is never executed. In order for the onSubmit() callback on your form to be called upon clicking the "Subscribe" button, the button needs to have a type="submit" attribute on it.
i.e.,
const handleSubmit = () => { ... }
return (
...
<Box
onSubmit={handleSubmit}
>
<TextField ... />
<Button
type="submit" <-- Add this in order to call onSubmit() upon click
>
Subscribe
</Button>
</Box>
...
Edit:
OP is using the MailChimp API from the client. The MailChimp API will not work on the client side. You can only use the MailChimp API on the server side.
However, you can utilize MailChimp's embedded form action URL to subscribe to user's emails on the client side (in a React component). You can avoid the user from being forwarded to MailChimp by sending a fetch POST request with the embedded form action URL.
This below example may need some tweaking, but this is the general idea on how this can be accomplished.
function handleSubmit(event) {
event.preventDefault();
// fetch URL is from MailChimp embedded form action url.
fetch('http://mailchimp.us8.list-manage.com/subscribe/post', {
method: 'POST',
// Not sure if MailChimp used urlencoded or json. You can modify this request to use either.
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'u': 'a123cd45678ef90g7h1j7k9lm', <-- found in embedded form code.
'id': 'ab2c468d10', <-- found in embedded form code.
'MERGE0': email, <-- email to be subscribed.
})
});
}
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));
I've got a fairly complex Next.js site that is mostly statically rendered and I'm adding Algolia search into the site. The mechanics of Algolia require that you use their API and notify them of additional content every time it gets published.
My question is where in the Next app you notify Algolia. Given that my site is using getStaticProps to fetch data, I figured this is the logical place to notify and update Algolia. It works but wondering what others have done, best practice, tradeoffs, etc.
The lifecycle looks like this:
Get data from database via GraphQL (using headless CMS Prismic)
Normalize data inside Next before sending to Algolia
Send data to Algolia (their system reconciles old/new records be referencing uuid)
Code that makes this happen:
// Use nextjs getStaticProps, destructure default params
export async function getStaticProps({ params, preview = false, previewData }) {
// Data fetch (assume getAllNewsForLandingPage gets an array of obj)
pageData.data = await getAllNewsForLandingPage(params.uid, previewData)
// Format and normalize results
const algoliaFormattedData = dataFormatter(pageData.data)
// Send data back to Algolia, who will reconcile old and new data automatically
await AlgoliaIndex.saveObjects(algoliaFormattedData)
}
I am new to both React-JS and Oboe.js. I am trying to speed up loading of some JSON data by using Oboe to stream the results. Unfortunately I am unable to do an update state in the function block. So I try to call another function that does the stateSet. Below is a method I have tried but doesn't work. It errors out a mapping function that uses search-results to render it in a table.
var that = this;
oboe({
url: //url,
method: 'POST', // optional
body: //POST-DATA, // optional
})
.on('node', '*', function(things){
that.updateState(things);
// This callback will be called everytime a new object is
// found in the foods array.
console.log( 'Go eat some', things.id);
});
updateState = (props) => {
this.setState({search-result: props});
}
What I am not sure about is the right way of updating a state with oboe.js and React?
Is there a better library to use for streaming JSON data into React?
Recommended approach
If you have the ability to change things server-side, then I would not recommend using Oboe for this. Oboe is useful if your only alternative is to load a large JSON object and you would like to access that data before the whole thing can be parsed.
The best way to optimize loading a lot of data on a client is to send less data at a time and to make multiple requests. A web-socket is the best approach, and Socket.io is a good tool for doing that.
If you need to use Oboe
I'm working to put together an example of oboe.js + react for you to look at, though it's tricky as much of the activity of Oboe happens outside the React lifecyle. I'll update this answer with that example 👍
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.