While you’re learning AJAX and Fetch it’s helpful to have a practice REST API to work with. CrudCrud is a service that provides a REST API backend that is customizable to whatever you’re working on.
It doesn’t have a lot of documentation, so here’s a simple guide on how to use it with Fetch.
Resources
In your app you’ll have some resources that you want to save on the backend. They may be posts or tasks or shopping cart items. Or spaceships.
To save them with CrudCrud, you’ll pick a name for your resource (like “spaceships”) and use it with your CrudCrud endpoint. CrudCrud will do all the work to set it up on the backend.
With spaceships it might look something like this:
https://crudcrud.com/api/6258dc47698c4d72/spaceships
You can have multiple resources on your CrudCrud endpoint, maybe like this:
https://crudcrud.com/api/6258dc47698c4d72/spaceships
https://crudcrud.com/api/6258dc47698c4d72/planets
https://crudcrud.com/api/6258dc47698c4d72/wormhole-gates
Naming Best Practices
There are many ways to name your resources, but here are some best practices
- It should be a noun.
Ex: spaceships not getSpaceships - It should be plural.
Ex: planets not planet
(there are some exceptions, such as when there will only ever be one) - It should be all lowercase letters.
Ex: spaceships not Spaceships or SpaceShips - It should use dashes in place of spaces.
Ex: wormhole-gates not wormhole_gates - It shouldn’t be shortened.
Ex: wormhole-gates not wh-gates
Tips
A few things to be aware of:
1)
We’ll save our endpoints in const variables so they’re only written out in one place. Like this:
const API_ENDPOINT = "https://crudcrud.com/api/6258dc47698c4d72";
const SPACESHIPS_ENDPOINT = API_ENDPOINT + "/spaceships";
const PLANETS_ENDPOINT = API_ENDPOINT + "/planets";
const WORMHOLE_GATES_ENDPOINT = API_ENDPOINT + "/wormhole-gates";
2)
Fetch uses promises. That means when we call fetch()
it doesn’t wait to get a response back, it immediately returns a promise object. At some point that promise will be fulfilled and make the response available.
If we want to wait until the promise is fulfilled (in this case, meaning the response has come back from the backend), before the code continues, we can use the await
keyword.
Any function that uses the await
keyword inside needs to be marked as async
.
You could also use the .then()
method, but in these examples I will use await
.
3)
If we log a response from fetch()
to the console, it looks something like this:
If we need to get actual JSON data from a response we’ll use the .json()
method to parse the body into JSON.
await response.json();
If our response was from a GET request for all the planets, that might give us something like this:
[
{
_id: 0,
name: "Tatooine",
habitable: true
},
{
_id: 1,
name: "Dagobah",
habitable: false
}
]
4)
When we need to send JSON to our API, we’ll turn it into a string like this:
JSON.stringify(objectOrArrayToStringify)
Stringifying our JSON will turn this:
{
name: "Dagobah",
habitable: false
}
Into this:
'{"name":"Dagobah","habitable":false}'
And it’ll be ready to send to our backend.
5)
CrudCrud stores its ids in a property called _id. If you need to access the id of an object, make sure you don’t forget the underscore.
resource._id
Read All
To get a list of resources, make a GET request to the resources endpoint.
fetch(RESOURCES_ENDPOINT)
(We don’t need to specify a method when we’re using Fetch to make a GET request because it will use GET by default.)
For example, we can get the list of planets:
const response = await fetch(PLANETS_ENDPOINT);
const planets = await response.json();
And now our planets
variable will have an array of our planet objects.
[
{
_id: 0,
name: "Tatooine",
habitable: true
},
{
_id: 1,
name: "Dagobah",
habitable: false
}
]
If we haven’t created any planets yet, it will be an empty array: []
Read One
To get one resource, make a GET request to the resources endpoint with the id of the resource on the end of the URL.
fetch(RESOURCES_ENDPOINT + "/" + id)
If we want to get the shapeship with the id of 4, we can ask for it like this:
const response = await fetch(SPACESHIPS_ENDPOINT + "/4");
const razorCrest = await response.json():
This function will get any spaceship from the backend by its id:
const getSpaceshipById = async (spaceshipId) => {
const resp = await fetch(
SPACESHIPS_ENDPOINT + "/" + spaceshipId
)
return await resp.json();
}
Create
To save a newly created resource to the backend, make a POST request to the resource endpoint.
fetch(RESOURCE_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newResourceData)
})
The variable newResourceData
should be an object with all the properties we want on the new resource.
If we want to create a new planet with this data:
const planetData = {
name: "Mandalore",
habitable: true
}
We can create it like this:
const response = await fetch(PLANETS_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(planetData)
})
const mandalore = await response.json();
The variable mandalore
will be the newly created planet with the id.
{
_id: 2,
name: "Mandalore",
habitable: true
}
If you need to, you can use that response to update the frontend data with the id. Or you can just refresh the whole list by sending a GET request for all the planets.
Update
To update the data on a resource, make a PUT request to the resources endpoint with the id of the resource on the end of the URL.
fetch(PLANETS_ENDPOINT + "/" + resourceId, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updatedResourceData)
})
The variable resourceId
should be the id of the resource to update.
The variable updatedResourceData
should be an object with the updated properties of the resource.
CrudCrud has 2 rules for the object in updatedResourceData
.
- It cannot have an
_id
property. This means we cannot just send the updated object. We have to make a copy without the_id
property. If we don’t, the request will fail and we’ll get an error. - It must have all the properties of the resource, even properties that are staying the same. Any properties we leave off will be removed from the resource.
Not all backend APIs have those same rules. Each API has its own specific expectations for requests. But CrudCrud will not update the resource correctly if we don’t follow those rules.
If, on the frontend, this planet:
const planet = {
_id: 7,
name: "Mustafar",
habitable: true
}
Has been updated and the habitable
property has been set to false
:
const planet = {
_id: 7,
name: "Mustafar",
habitable: false
}
We can save that to the backend like this:
const planetWithoutId = {
name: planet.name,
habitable: planet.habitable
}
const response = await fetch(
PLANETS_ENDPOINT + "/" + planet._id,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(planetWithoutId)
}
)
(We don’t need the .json()
method here because CrudCrud doesn’t return any data from a PUT request.)
If we left off the name
property from planetWithoutId
then the name
would get removed and Mustafar would look like this:
{
_id: 7,
habitable: false
}
So make sure to include all the properties, even properties that are staying the same.
Cool Tip
We can make a copy of an object without one property using object destructuring and spread syntax. It looks like this:const { _id, ...copyWithoutId } = objectToCopyWithoutId
I didn’t use that method above for clarity, but it can save a lot of hassle with bigger objects.
Delete
To delete a resource, make a DELETE request to the resources endpoint with the id of the resource on the end of the URL.
fetch(PLANETS_ENDPOINT + "/" + resourceId, {
method: "DELETE"
})
We don’t need headers or a body because there’s no data to send.
If we want to delete this planet:
const planet = {
_id: 9,
name: Alderaan,
habitable: true
}
We can do that like this:
const response = await fetch(
PLANETS_ENDPOINT + "/" + planet._id,
{ method: "DELETE" }
)
(We don’t need the .json()
method here because CrudCrud doesn’t return any data from a DELETE request.)
Conclusion
CrudCrud is a handy resource for practicing with AJAX, but it doesn’t have a lot of documentation. Hopefully with the help of this guide you can start using CrudCrud in your own practice projects.