Create, Read, Update & Destroy data fetching operations with APIs in React is similar to using JavaScript but have a bit more detail with regards to states and side effects. In JavaScript, the basic format of a fetch request looks like this:
fetch(`www.someapiurl.com/key`)
.then(response => response.json())
.then(data => console.log(data))
The result at the end of the fetch request is the information from the API. This is how it also works with React, but in order to make the page responsive we also have to update the state to reflect that information from the fetch request is added to the page or that the API has been altered.
Lets have an example of a GET fetch request. Like JavaScript, we use fetch to obtain the data from the API to use for what we want to display. React allows us to use state to make our pages dynamic in response to changes in states that we set. To utilize the dynamic changes, we first initialize the state for the data that we want as an empty array by importing and using the React hook useState()
which give us our state variable shows
and setter function setShows
for modifying the state. Imagine our objects in the API fetch request consist of only three keys of id
, title
with an associated string and likes
with an associated number.
import {useState} from 'react';
function App(){
const [shows, setShows] = useState();
Because we want to fetch and display the data when our page loads, we also import and use the useEffect()
hook, setting a callback function to perform the GET fetch request for our App
component and setting an empty dependency array as the second argument to make sure this code only runs once to fetch the data that we initially need. Once the data is fetched, we can use the setter function setShows
to set the data as our state variable shows
.
import {useState, useEffect} from 'react';
function App(){
const [shows, setShows] = useState();
useEffect(()=> {
fetch(`www.someapiurl.com/key`)
.then(response => response.json())
.then(data => setShows(data));
//this gives us the data from API set as the shows array state variable
};
const allShowTitles = shows.map( show => ( <p key={show.id} > {show.title} Likes: {show.likes} </p> ) )
return ( <div> <section> {allShowTitles} </section> </div> );
};
//this example gives us a div element for each object in the shows array with the object's key of `title` listed
The page will update to display the information retrieved from the external API by the time setShows
changes the variable of shows
at the end of the useEffect()
callback, which also causes our component App
to give us a <p>
element for each object in shows
.
For a POST request, we need to set a separate handler function to change the state in accordance to the POST request being properly processed in order to reflect the new data added to the API. The function for fetching the POST request should be assigned to the onSubmit
handler for the form of the information being added to the API. For example, lets say the AddShowForm
is a child of App
.
function App(){
//other code from earlier is above
function handleAddShow(addedShow){
setShows([...shows , addedShow])
}
return ( <div> <section> <AddShowForm onAddShow={handleAddShow}/> </section>
<section> {allShowTitles} </section>
</div> );
}
-----------
function AddShowForm({onAddShow}){
const [form, setForm] = useState("");
function handleChangeForm(e){
setForm(e.target.value)
}
function handleSubmit(e){
e.preventDefault;
fetch(`www.someapiurl.com/key`, {
method: "POST",
headers: {
"Content-Type": "application/json"},
body: JSON.stringify({ title : form , likes : 0})})
.then(resp => resp.json())
.then(addedShow => onAddShow(addedShow))
}
//the contents of body undergoing .stringify should match the key & value formatting of the individual objects in the api
//the data in the second .then is the object that was added to the api at the end of the POST request
return (<form> <input type="text" value={form} onChange={handleChangeForm} name="title" />
<input type="submit" onSubmit={handleSubmit} /> </form>)
}
The function handleAddShow
is located on the same component as the state variable shows
and is passed down as a prop onAddShow
to the child component AddShowForm
where the form for making the POST request is set up. Here, we have a callback function handleSubmit
that activates when the form is submitted which triggers the POST request. The response back is the object that we added to the API, which we can then use as the argument for invoking onAddShow
, which is handleAddShow
in App
. Inside handleAddShow
the setter function setShows
sets the state variable in the form of an array of objects, here we use the spread operator ...
on shows
to pull the objects of what we already have and after ...shows
is the new object obtained back from the fetch request. The state updates to reflect the change in the API and the page updates with the information of the new show
we added.
PATCH requests handled in React are similar to POST requests but with the added detail of pointing to the proper object in the API, usually by id. As an example we can use a button to add likes to a show
.
function App(){
//other code from earlier is above
function handleEditShow(changedShow){
const updatedShows = shows.map(show => {
if(show.id===changedShow.id){return changedShow}
return show
})
setShows(updatedShows)
}
const allShowTitles = shows.map( show =>{
function likeClick(){
fetch(`www.someapiurl.com/key/${show.id}`, {
method: "PATCH",
headers: {
"Content-Type":"application/json",},
body: JSON.stringify({likes: show.likes + 1})
})
.then(resp=>resp.json())
.then(changedShow => handleEditShow(changedShow))
};
return ( <p key={show.id} > {show.title} Likes: {show.likes} <button onClick={likeClick}> Like! </button> </p> ) })
return ( <div>
<section> {allShowTitles} </section>
</div> );
}
Here we added a button
and likeClick
function in the .map
method to each show
displayed that causes a PATCH request when clicked. Each button has a different fetch request url because we interpolated every individual show
id, ensuring we have the correct object to be changed. Similar to the POST request, we end the fetch request by putting the returned data changedShow
as an argument in handleEditShow
where we use .map
on shows
to create updatedShows
. All unupdated shows are returned by .map
while changedShow
with the matching id in our conditional is returned instead of the original show
with the corresponding id. updatedShows
is then passed into setShows
which changes the state and causes the page to update with the Likes of the show attached to the clicked button
increasing by 1.
Finally, a DELETE fetch request is similar to PATCH, also with a small change.
function App(){
//other code from earlier is above
function handleDeleteShow(deletedShow){
const updatedShows = shows.filter(show => show.id!==deletedShow.id);
setShows(updatedShows)
}
const allShowTitles = shows.map( show =>{
function deleteClick(){
fetch(`www.someapiurl.com/key/${show.id}`, {
method: "DELETE" })
.then(resp=>resp.json())
.then(handleDeleteShow(show))
};
//there is no data returned at the second .then, so we pass the original object we used to make the request into handleDeleteShow
return ( <p key={show.id} > {show.title} Likes: {show.likes} <button onClick={deleteClick}> Delete? </button> </p> ) })
return ( <div>
<section> {allShowTitles} </section>
</div> );
}
We add a button to each show
with an onClick
of deleteClick
, using interpolation to give each show
a unique url for the DELETE request. After the fetch, the show
deleted from the API is passed into handleDeleteShow
and from there .filter
is used on shows
to create the updatedShows
variable. .filter
removes the show
with the associated deletedShow
id from the array, and updatedShows
is passed into setShows
to change the state causing the page to update with the deleted show
object being removed from display. Fetch requests in React makes pages more responsive allowing us to reflect server side changes in our client side pages and still works the same as with JavaScript.
Resources
Using the State Hook (https://reactjs.org/docs/hooks-state.html)
Using the Effect Hook (https://reactjs.org/docs/hooks-effect.html)
Flatiron School (https://flatironschool.com/)
Top comments (0)