In this post you’ll learn how to use the fetch
API to POST
JSON data to a backend service.
For the purposes of this article we’re going to create a form and submit it and POST
that data off to a backend service using fetch
.
First, let’s create the form with a name
attribute to capture the data we’ll POST
:
<form name="fetch">
<input type="text" name="message" placeholder="Tell me something!">
<button type="submit">Submit</button>
</form>
To get a reference to our form we can use document.forms
and reference the name="fetch"
we supplied:
const form = document.forms.fetch;
const handleSubmit = (e) => {
e.preventDefault();
};
form.addEventListener('submit', handleSubmit);
For good measure, we’ve setup an event listener to handle the submit
event.
Next, let’s get the JSON payload we want to send to our server.
I’m skipping over the details, but we can combine new FormData
with Object.fromEntries
to get a serialized object of our form’s values. Our form contains one input with a name="message"
, hence our message
property in the body
object.
This means if we supply our e.target
(our event target, the form
into FormData, it will construct an object of key/value pairs for us to use). Once we’ve got that, stringify the data and it’s ready to send:
const handleSubmit = (e) => {
e.preventDefault();
const body = JSON.stringify(Object.fromEntries(new FormData(e.target)));
// { message: 'Hey there!' }
console.log(body);
};
Free eBook
Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.
- Observables and Async Pipe
- Identity Checking and Performance
- Web Components <ng-template> syntax
- <ng-container> and Observable Composition
- Advanced Rendering Patterns
- Setters and Getters for Styles and Class Bindings
Let’s introduce fetch
inside a new function to abstract away our logic:
const postForm = (body) => {
return fetch('//httpbin.org/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body
});
};
What’s different from a typical fetch
call? You can see that we’ve had to specify a Content-Type
header and set the value to application/json
. Don’t forget the method: 'POST'
or you won’t be posting anything.
I’m accepting body
as the function argument, so I’m leaving the variable to be dynamically added and named as body
, which is where we supply the data to be sent via fetch
.
Now inside our submit function, we can .then()
our returned Promise from fetch
(yes, we get a Promise back, so we could use .then()
or async await - I’ll show you both routes):
const handleSubmit = (e) => {
e.preventDefault();
const body = JSON.stringify(Object.fromEntries(new FormData(e.target)));
postForm(body)
.then(res => res.json())
.then(data => console.log(data.json));
};
You’ll note here that our first Promise resolution involves res
which we then return res.json()
, this is a crucial step that if you miss would result in errors.
Once our res.json()
Promise has also been resolved, we can then deal with the raw data
we get back - it just so happens that the service URL we’re making the POST
to returns an object with .json
on it, so we’ll reference it in our console.log
.
Using async await and refactoring our handleSubmit
function to be async
, we could do this:
const handleSubmit = async (e) => {
e.preventDefault();
const body = JSON.stringify(Object.fromEntries(new FormData(e.target)));
const res = await postForm(body);
const data = await res.json();
console.log(data.json);
};
You can see the async/await pattern is nice alongside fetch
, where we can treat our asynchronous code as if it was executing synchronously - helping us clean up our code and avoid nesting .then()
calls.
If you are serious about your JavaScript skills, your next step is to take a look at my JavaScript courses, they will teach you the full language, the DOM, the advanced stuff and much more!
Check out the live demo on Stackblitz, enter a message and submit to watch the fetch
api POST
our JSON data:
Thanks for reading! Happy fetching.