What are React Hooks?
If you are brand new to React and APIs consider checking out:
Either of the articles can provide a decent introduction to React and the relationship with APIs. Otherwise, you have probably at least heard of React hooks.
Earlier on in React, components were either class components or functional components. Functional components were Javascript functions that accepted props (data) to display and returned JSX.
Class components typically required more code but could store state variables and could use lifecycle methods. This made class components the go-to option for making API calls, processing user input, etc. Functional components became useful helpers for class components.
The Trouble with Functional Components
The relationship between class and functional components made sense until the moment functional components needed to do things that only class components could do (i.e hold state, respond to lifecycle changes).
Consequently, functional components would be converted to class components or class components were created as wrappers for functional components. This was inconvenient and all changed with React version 16.8.
The Introduction of React Hooks
React hooks were introduced in version 16.8 and are widely accepted. With hooks, class components didn’t need to be converted to functional components, which meant hooks didn’t break anything in the current class and functional components. Hooks are “opt-in”. The only requirement was that other React packages, like React DOM, needed to be compatible with version 16.8 of React.
Let’s give a small example of what adding hooks to a functional component looks like.
The below code represents what a simple functional component may look like.
import React from 'react' const Example = (props) => ( <h1>{props.greeting}</h1> ) export default Example
At some point in the progression of the application, let’s say the developers wanted to translate the greeting to a different language. This could require an API call to the translation service and a state variable to hold the new greeting. Those are two things the old functional components could not do.
In the old React, this component would probably be converted to a class component, or a parent class component would be built. Unfortunately, the parent class component may already have a lot of code and a large state. Our code becomes easier to maintain as the functional component becomes versatile. Therefore, with hooks, conceptually, the component can easily obtain the functionality required.
import React from 'react' const Example = (props) => { let [translation, setTranslation] = React.useState('') // state hook React.useEffect(() => { // side effect hook // call API with props.greeting parameter setTranslation(response.data.translation) }, [setTranslation]) return ( <h1>{translation}</h1> // use state in component ) } export default Example
useState
is introduced at the top of the function to store the translated text. useEffect
is called when the component mounts and sets the translation variable when the API is done.
useState and useEffect
If you are new to hooks, seeing functions like useEffect
or useState
can seem foreign. However, these will become common to you as they are some of the most commonly used hooks in React.
useState
I have already mentioned that the useState
hook provides a state variable to the functional component. The value inside the function call, an empty string, is the initial value of the variable.
[translation, setTranslation]
utilizes Javascript’s object unpacking capabilities to extract the variable translation
and the function to set the variable, setTranslation
.
Notice we are using both the variable for its value, and the function to set the value, in the example above.
useEffect
This hook requires more know-how because it expects an argument of dependencies to be provided with the implementation. useEffect
takes in two arguments.
- Callback function
- array of dependencies
In the example above, the callback function argument is represented by an unimplemented API call. Furthermore, the only dependency that the hook has is the setTranslation
function.
It’s important to provide the dependencies to communicate to the function when, or if, it needs to change. Dependencies can be tricky, and using a linter when running a development server can help you tremendously in the process.
useEffect vs. componentDidMount
componentDidMount
became a popular lifecycle function in class components because it was the ideal way to fetch data for the component. This is something that both useEffect
and componentDidMount
have in common.
However, componentDidMount
is only supposed to run at the beginning of the lifecycle and then become dormant. useEffect
runs when the component mounts but also can run at any time when dependencies change. Therefore, if no dependencies are passed to the second argument array, or if the dependencies always change, the function continues to run (sometimes causing an infinite loop).
To have the useEffect
only run once when the component mounts remember to pass an empty array as the second argument (or pass an array with the necessary dependencies).
Learning more about hooks
Hooks can take a while to pick up on, and there are quite a lot of them. Furthermore, developers can create custom hooks, which is a new fun thing to explore in React. However, I would recommend getting the built-in hooks down first.
If you still want to learn more about hooks, I would start with the introduction to hooks or the frequently asked questions about hooks on reactjs.org, and then coming back to build the example application!
Quotes API
Free multilingual API for random famous quotes in many languages.
The Quotes API is a useful API for getting started with using HTTP requests, testing out RapidAPI, and combining those technologies with ReactJS.
The API only has one endpoint, Random Quote, that allows it to be understood quickly.
This, of course, is not the only quote API on the marketplace. Regardless, some of the advantages are:
- Free and unlimited
- Support for many languages
- Return the best quotes curated by users
If you want to see more quote API options check out this link.
How to Fetch Data from an API with React Hooks
Prerequisites
- You’ll need to have Node >= 8.10 and npm >= 5.6 on your machine.
- Familiarity with React components, CSS, and HTML.
- Internet connection.
- A text editor (I am using Visual Studio Code).
- Understanding of how to open a terminal, or command-line on your machine
1. Set Up the Application
The application is bootstrapped with create-react-app. Therefore, we need to open up a new terminal and execute a command that builds a starter React app.
Open up a new terminal and run npx create-react-app rapidapi-using-react-hooks
. The command takes a couple of minutes to execute. Then, change directories into the project and open up your text editor in the project’s root folder.
Using the terminal, this is done with the command cd rapidapi-using-react-hooks
.
In the project’s root, download the HTTP request library Axios.
npm install --save axios
Next, start the app by running npm start
.
In the browser, visit http://localhost:3000. You should see the following page.
Well done!
2. Sign Up For a Free Account on RapidAPI
To use the Quotes API in the next section with React hooks, you will need an account. Visit RapidAPI to get signed up!
3. Subscribe to the Quotes API

Notice I have already subscribed to the Basic plan, therefore I have a link to Manage and View Usage that takes me to the developer dashboard.
You can track your API usage on the dashboard in case you have concerns about approaching your quota for any of the APIs that you subscribe to.
4. Fetch Data with useEffect
First, remove all the JSX code in the <header>
inside of the file src/App.js
and replace it with the following HTML.
.... <h1> Fetching Data with React Hooks </h1> ....
The application running at http://localhost:3000 should reflect these changes.
Next, it’s time to add our first hook in App.js
.
Add a state variable using the React hook useState
at the top of the function.
.... function App() { let [responseData, setResponseData] = React.useState(''); // new return ( <div className="App"> ....
useEffect
Let’s explore the useEffect
hooks before setting it up to make an API call.
The next step is to add useEffect
to the file and give the variable responseData
a value when the component loads.
.... function App() { let [responseData, setResponseData] = React.useState(''); React.useEffect(() => { setResponseData('hello') console.log(responseData) }, [setResponseData, responseData]) return ( <div className="App"> ....
Inspect the developer console and notice that the variable’s value is set every time we refresh the page and logged to the console.
This is the process that we need to use for the API call.
- State variable is ready to store the response data
- API call happens when the component is mounted
- Response data is saved to the state variable
Add API Call
Earlier, we installed Axios for making HTTP requests. Now, let’s add the API call to useEffect
. Also, we are going to add some JSX code to the component to display the raw response data.
However, we are going to need the RapidAPI key available for the API call. WARNING: The following process does not secure your API key for production and is only used for the sake of this tutorial.
You can read about React app environment variables by following this link.
Create a file .env
in the project root. Inside the file add the code;
REACT_APP_API_KEY=yourapikey
You can get your API key by visiting the API dashboard page,
Restart the application in the terminal so the environment variable can be loaded in.
Next, replace the code inside of React.useEffect()
with,
.... axios({ "method": "GET", "url": "https://quotes15.p.rapidapi.com/quotes/random/", "headers": { "content-type": "application/octet-stream", "x-rapidapi-host": "quotes15.p.rapidapi.com", "x-rapidapi-key": process.env.REACT_APP_API_KEY }, "params": { "language_code": "en" } }) .then((response) => { setResponseData(response.data) }) .catch((error) => { console.log(error) }) ....
Import Axios at the top of the page with the line import axios from 'axios'
.
The new function above does not use responseData
, therefore, it can be removed as a dependency for the useEffect
function.
Finally, below the <header>
JSX tag, add this code so we can see the response data that is being fetched,
.... <pre> <code> {responseData && JSON.stringify(responseData, null, 4)} </code> </pre> ....
You should now see new response data displayed every time the page loads!
5. Display API Data with React Hooks
The application is not very appealing, despite successfully fetching the response data.
Fortunately, we can see the response data and can use dot-notation to extract the data that we need.
Add the following JSX code below the <header>
tag (you can comment out, or delete, the <pre>
block that we just added).
.... <main> {responseData && <blockquote> "{responseData && responseData.content}" <small>{responseData && responseData.originator && responseData.originator.name}</small> </blockquote> } </main> ....
Now, we just get the content
and originator
data, but what if we want a different quote?
It would be nice to have the API call in a function that we can call, not only in useEffect
, but also from the click of a button.
- Move the API call into a function named
fetchData
. - Call the function in
useEffect
- Update
useEffect
‘s dependencies - Add a button to the JSX code that can call the function
fetchData
Unfortunately, this setup causes the useEffect
hook to continuously be called because of the side effects of the API call in the new fetchData
function.
To stop the infinite loops we utilize the useCallback
hook. This hook returns a memoized callback that only changes if the dependencies of the function change. This hook can be a lot to digest when starting out, so I am not going to explain it in depth. Let’s focus on the two most commons hooks that we have already used.
The final version of App.js
, using three different React hooks to orchestrate the API call, is;
import React from 'react'; import axios from 'axios'; import './App.css'; function App() { let [responseData, setResponseData] = React.useState(''); const fetchData = React.useCallback(() => { axios({ "method": "GET", "url": "https://quotes15.p.rapidapi.com/quotes/random/", "headers": { "content-type": "application/octet-stream", "x-rapidapi-host": "quotes15.p.rapidapi.com", "x-rapidapi-key": process.env.REACT_APP_API_KEY }, "params": { "language_code": "en" } }) .then((response) => { setResponseData(response.data) }) .catch((error) => { console.log(error) }) }, []) React.useEffect(() => { fetchData() }, [fetchData]) return ( <div className="App"> <header className="App-header"> <h1> Fetching Data with React Hooks </h1> <button type='button' onClick={fetchData}>Click for Data</button> </header> <main> {responseData && <blockquote> "{responseData && responseData.content}" <small>{responseData && responseData.originator && responseData.originator.name}</small> </blockquote> } </main> {/* <pre> <code> {responseData && JSON.stringify(responseData, null, 4)} </code> </pre> */} </div> ); } export default App;
Add CSS
You have probably noticed that the app is still missing some style and is difficult to interact with.
Replace all the code in App.css
with this code,
.App { background-color: #282c34; text-align: left; width: auto; min-height: 100vh; } button { margin: auto; padding: .25rem .75rem; font-size: 1.2rem; cursor: pointer; background: rgb(255, 119, 0); color: white; border: 2px solid rgb(255, 119, 0); border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; } h1 { margin: 1.2rem auto; font-family: sans-serif; font-size: 3.5rem; } blockquote { border-top: 2px solid rgb(255, 119, 0); border-bottom: 2px solid rgb(255, 119, 0); font-size: 2rem; margin: 5% 8%; font-weight: 200; padding: 2%; } small { display: block; font-size: 0.7em; text-align: right; font-style: italic; margin: 10px; padding: 4px; } .App-header, .App { display: flex; flex-direction: column; align-items: center; justify-content: center; color: white; } .App-link { color: #61dafb; }
With that, the app comes to life!
The application will fetch a quote to display when the component mounts because of the function call in useEffect
. Then, if the user wants a new quote they can click the button later on!
Conclusion
I hope you enjoyed exploring how dynamic React hooks can be within a component. Remember, class components are not useless, and can still be used effectively to create React applications.
However, the introduction of hooks and custom hooks can open up a new door of creativity and efficiency when developing in ReactJS.
If you have any questions about the implementation of the hooks, or about the example application, please leave a comment below!
Leave a Reply