DEV Community

Hunter Becton
Hunter Becton

Posted on • Originally published at Medium

Build a React Accordion Component Using React Hooks

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)