Build a React Accordion Component from Scratch Using React Hooks
In this tutorial you will learn how to create an animated React accordion component using React Hooks like useState
and useRef
.
What are React Hooks?
In simplest form, React Hooks make it possible to use state without the need to create a class. If that’s enough to sell you on using Hooks, then read (or watch) on. However, if you’d like a deeper dive into React Hooks check out Making Sense of React Hooks by Dan Abramov, co-author of Redux and Create React App.
You can get the final code here from CodeSandbox.io. I’ve also recorded the entire process in the video below and outlined each step in the subsequent post–enjoy!
Final Project
Create a React App in CodeSandbox.io
To get started head to CodeSandbox.io and sign up with your GitHub account. CodeSandbox is a web-based code editor that makes it easy to write code and create web applications without the need to setup anything locally on your computer–perfect for a quick tutorial.
Once you’re on the dashboard click on the Create Sandbox button and select the React Client Template. This will create a basic React application that you can start using to build the accordion.
Before you start writing the accordion component the first thing you want to do is remove the out-of-the-box styling in the styles.css
file. Then add the following global styles:
Setting box-sizing: border-box
ensures that padding is added to the inside of elements while margin: 0
and padding: 0
ensures the browser isn’t adding any default padding to elements.
Create the Accordion Component
After cleaning up some of the boilerplate code go ahead and create a new folder in your project called Components
. Inside this folder create two files: Accordion.js
and Accordion.css
. You’ll start with the most basic version of the accordion component, only passing in props and not using React Hooks. You’ll add React Hooks later in the tutorial. With that said, open the Accordion.js
file and add the following:
In this code you created a simple function (stateless) component, passing in props. One prop you used is dangerouslySetInnerHTML
. It’s important to note that improper use of dangerouslySetInnerHTML
can open you up to a cross-site scripting (XSS) attack. Before using dangerouslySetInnerHTML in your project be sure to read How to prevent XSS attacks when using dangerouslySetInnerHTML in React by Jacob Jang.
With the most basic form of the accordion component built you can now import it into your index.js
file and use it in the return, passing in props for title
and content
like so:
For the demo I used LoremIpsum.io to generate filler text. It’s also important to note that in the last accordion I wrote HTML within the content prop in order to show you how dangerouslySetInnerHTML
will render HTML within a string.
Create the Accordion CSS Styles
Now it’s time to style the accordion component by writing the following in the Accordion.css
file:
I’ll spare too much detail here and refer to the comments I left in the CSS file to explain what the classes are doing. However, I do think it’s important to point out that you’ll be passing in some styles like .active
and .rotate
to React state later in the tutorial. Also, the transition
property is being used on classes like accordion__icon
to create smooth animated transitions when a CSS property changes or when new classes are added to elements.
Create the Chevron Component
Each accordion will have a chevron on the right side that will rotate to point downwards when active. To create the chevron you’ll start by going to FontAwesome.com and downloading the SVG for the chevron-right icon. Here’s a quick GIF on how to do that:
Once the SVG finishes downloading open it in a text/code editor of choice. Then copy everything in the file and head back to CodeSandbox. Once you’re there create a new file in the Components
folder called Chevron.js
and write a simple function component, passing in what you copied from the SVG in the return like so:
Notice the props this component is using: className
, height
, width
, and fill
. You’ll use those in the Accordion.js
file like so:
Add React Hooks to the Accordion Component
Now let’s get to the real reason you’re here: React Hooks!
Implement useState: setActive and setActiveState
The first hook you’ll use is useState()
, which you’ll add to your Accordion component. With hooks there’s no need to convert a function component into a class component–just initialize the hook like so:
First, you’ll need to import useState
from React. Then you’ll use array destructuring syntax to set the current state value (setActive
) and function that allows you to update the state (setActiveState
). This new constant is set equal to useState
and the only argument useState
needs is the initial value, which in this case is an empty string.
Create the toggleAccordion Function
Now that you have your first state defined you need to create a function within the component that will be called when the accordion is clicked by an user. To make sure it’s clear what the function does, you can name it toggleAccordion
.
This first thing this function will do is call setActiveState()
. Within setActiveState()
you’ll write the following ternary operator: setActiveState(setActive === “” ? “active" : “”
. This ternary operator is checking if setActive
is empty, and if it is it will change the state to active. If it is already set to active
it will set it to an empty string.
You can then use the value of setActive
within the button className
using a template string. Last, pass an onClick
event listener that calls the new toggleAccordion
function:
Now when you save your project you can click on the accordion and the background color will stay the value you set on the .active
class in your Accordion.css
file. You can always inspect the element to see the class toggle from accordion
to accordion active
.
Implement useRef to Identify scrollHeight
The next React Hook you’ll use in the tutorial is useRef()
. This hook will create a reference to a DOM element, which you can then get data off of by accessing .current
. The data you want to access is scrollHeight
, which gives you the height of an element even when the element’s overflow is hidden.
You then can use the data from scrollHeight
to change the max-height of the content within the accordion, which you’ll initially set to 0. Doing this will create an animated expand/collapse effect for the accordion content.
To start you need to import useRef
from React and initialize it within the accordion component. You can call this reference content
so it’s easy to remember what it’s referencing. You’ll also want to set its initial value to null
.
Then you can set the reference on the content element by passing in the following HTML attribute: ref={content}
.
In order to see the value of each reference you can console.log
the value in the toggleAccordion
function. By now you should have the following code:
Now you can open the console within CodeSandbox and see the scrollHeight
of each accordion content section printing to the console when you click on it. Feel free to remove the console.log
once you’re done testing it out.
Implement useState: setHeight and setHeightState
With access to the accordion’s content height you can now use that value to create the animated expand/collapse effect. To start you’ll need to create a new state called setHeight
with useState
–just like you did for setActive
.
This time set the initial state to 0px
because you’ll be using that value to make sure all the content is hidden when the accordion components are rendered.
You’ll also change setHeight
using setHeightState
, which you’ll call in the toggleAccordion
function. Just like with setActiveState
you will write a ternary operator, but this time you’re checking if setActive
is equal to active
. If it is the function will change setHeight
to 0px
. Else, if it’s already 0px
it will change to the value of the accordion’s content scrollHeight
.
Finally, you’ll use the value of setHeight
to set the maxHeight
via an inline style. With that your code should appear as follows:
Once you save that you can click on each accordion to reveal the content. Feel free to change the speed and acceleration of the animation in the transition
property of the .accordion__content
class in your Accordion.css
file.
Implement useState: setRotate and setRotateState
You’re at the homestretch! The last thing you want to do is animate the chevron to point downwards by rotating it 90 degrees clockwise when the accordion’s setActive
state is active.
To do this you’ll create a new state called setRotate
. You’ll set the initial value equal to the string accordion__icon
and write a similar ternary operator in the toggleAccordion
function that checks the current value of setActive
. This time if setActive
is equal to active
the function will change the setRotate
value to accordion__icon
. Else, if it’s not active it will change setRotate
to accordion__icon rotate
. You’ll then use the value of setRotate
to dynamically change the className
of the chevron. Your Accordion.js
component should look like this:
And that’s it! Now when you click on an accordion the chevron will rotate downwards. Click again and the accordion will revert to its initial state.
Similar to .accordion__content
, you can tweak the animation by changing the transition
property on the .accordion__icon
class in your Accordion.css
file.
Finishing Words
I hope this tutorial was a great example of how to use React Hooks. If you enjoyed the tutorial be sure to check out my other courses on the Skillthrive YouTube channel. And as always, if you have any questions feel free to drop them below.
Top comments (0)