useEffect, Hook
In a previous blog, I dipped into the history of Hooks, how they came about and what Devs were attempting to accomplish(and did so elegantly I may add) by allowing us to use lifecycle methods in functional components, which allowed us to get away from using Class components without breaking code already in the wild. This time around I thought I take a quick look at another great Hook know as useEffect.
Side Effect
If your familiar with lifecycle methods, you can think of the useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount all wrapped up in one. This Hook is tapping into something know as side effects, these side effects are from doing certain operations such as data fetching, subscribing or changing the DOM in React components. So how do we go about using useEffect to create these lifecycle method, all with one Hook? Well I thought we take a look at using this operation in Data fetching(API calling)and compare it to lifecycle methods used to accomplish the same outcome.
useEffect
Typically if you were to fetch an API in Class component with React you end up with something like this …
import React from 'react'class App extends React.Component {
state={}, //initial state goes herecomponentDidMount() {
//fetch goes here
}componentUnmount() {
//clean up fetch
}render() {
return (
<div>
//render output
<div>
)
}
};export default App;
phew! Just the boilerplate alone is a task all itself. This does not even include the actual logic needed to call the API, clean it up and render it out. Fortunately for us, we can now useState and useEffect to accomplish these tasks directly in functions without having to build all this boilerplate code.
import React, { useState, useEffect } from 'react'export default function App() {
const [resourceType, SetResourceType] = useState('albums')
const [items, setItems] = useState([])useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/${resourceType}`) //removed /albums, added ${resourceType} to display each endpoint.then(response => response.json())
.then(json => setItems(json))
},[resourceType])
//any value change run useEffect hookreturn (
<div>
<button onClick={() => SetResourceType('albums')}> Albums </button><button onClick={() => SetResourceType('photos')}> Photos </button><button onClick={() => SetResourceType('users')}> Users </button><h5>{resourceType}</h5>
{items.map(item => {
return <pre>{JSON.stringify(item)}</pre>
})}
</div> //map over JSON
)
}
Lets break this down a bit….
import React, { useState, useEffect } from 'react'export default function App() {
const [resourceType, SetResourceType] = useState('albums')
const [items, setItems] = useState([])
...
First to get the actual JSON click here, its great for getting started with an API, without registering and getting an API key from the vendor. Next we are simply using useState, first to set our initial state for the resourceType to ‘albums’, and then using setResourceType to UPDATE the state your in. This is also being done on the next line with items, setItems, however instead of setting this to an initial state, we are setting this to an empty array, in order to take advantage of our code below.
...
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/${resourceType}`)//removed /albums, added ${resourceType} to display each endpoint
.then(response => response.json())
.then(json => setItems(json))
},[resourceType])
//any value change run useEffect hook
...
Second, we run are actual logic for useEffect. Here we are fetching our API, in this example however I am using /${resourceType} instead of /albums at the end in order to easily switch between the three endpoints we need for our render. We then return our JSON thru setItems which we defined above. Lastly on the end with [resourceType] we are making so anytime this side effect is changed it runs the useEffect hook to make the new call.
...
return (
<div>
<button onClick={() => SetResourceType('albums')}> Albums </button><button onClick={() => SetResourceType('photos')}> Photos </button><button onClick={() => SetResourceType('users')}> Users </button><h5>{resourceType}</h5>
{items.map(item => {
return <pre>{JSON.stringify(item)}</pre>
})}
</div> //map over JSON
)
}
Finally, we can render the output in our return. This part I think is very neat, with our onClick buttons we are using our setResourceType specifically to the one we want returned anytime the button is clicked. Then in the last bit of code we are mapping over the JSON in a <pre>(this is a tag used for preformatted text) with each one of those items. Our end result should look something like this when you click on any button …
From here you can obviously parse this out more, getting just the userId, id or title by chaining onto {JSON.stringify(item)} .
...
{items.map(item => {
return <pre>{JSON.stringify(item.userId)}</pre>
})}
...
Happy coding!