Build a React Accordion Component Using React Hooks
Tags: react, video, tutorial
Published: 2019-07-15 20:42:32

![](https://cdn-images-1.medium.com/max/3840/1*1DNWUA_ztdBffw3job4A4g.jpeg)

## 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](https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889) by [Dan Abramov](https://medium.com/@dan_abramov), co-author of Redux and Create React App.

You can get the final code [here](https://codesandbox.io/s/react-accordion-using-react-hooks-9uuvc) from CodeSandbox.io. I’ve also recorded the entire process in the video below and outlined each step in the subsequent post–enjoy!

{% youtube MAD2HnUFjgg %}


## Final Project

{% codesandbox 9uuvc %}


## Create a React App in CodeSandbox.io

To get started head to [CodeSandbox.io](https://codesandbox.io/) and sign up with your [GitHub](https://github.com/) 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:

{% gist https://gist.github.com/hunterbecton/5925bf604decf1ca1727fb195d53924f %}

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:

{% gist https://gist.github.com/hunterbecton/70421699a252bbb9e2c11dccb5ca9d94 %}

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)](https://en.wikipedia.org/wiki/Cross-site_scripting) attack. Before using dangerouslySetInnerHTML in your project be sure to read [How to prevent XSS attacks when using dangerouslySetInnerHTML in React](https://dev.to/jam3/how-to-prevent-xss-attacks-when-using-dangerouslysetinnerhtml-in-react-1464) 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:

{% gist https://gist.github.com/hunterbecton/917f18db0a0477dd564eb31932f29b8d %}

For the demo I used [LoremIpsum.io](https://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:

{% gist https://gist.github.com/hunterbecton/c9d5f84f92080c6ff00cd79450b071e6 %}

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](https://www.w3schools.com/css/css3_transitions.asp) 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](https://fontawesome.com/) and downloading the SVG for the [chevron-right icon](https://fontawesome.com/icons/chevron-right?style=solid). Here’s a quick GIF on how to do that:

![](https://cdn-images-1.medium.com/max/2000/1*9pXF7bc3omGIkDhmMPtLyQ.gif)

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:

{% gist https://gist.github.com/hunterbecton/e0828efa39a6f9e2cebbdfd15bc998e3 %}

Notice the props this component is using: `className`, `height`, `width`, and `fill`. You’ll use those in the `Accordion.js` file like so:

{% gist https://gist.github.com/hunterbecton/e88df83371e1edc77b7aae6284664b0e %}

## Add React Hooks to the Accordion Component

Now let’s get to the real reason you’re here: [React Hooks](https://reactjs.org/docs/hooks-intro.html)!

### 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:

{% gist https://gist.github.com/hunterbecton/f06aa025b750c335902af41c0ae24f2b %}

First, you’ll need to import `useState` from React. Then you’ll use [array destructuring syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Array_destructuring) 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_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:

{% gist https://gist.github.com/hunterbecton/034068304212b6ce3e108b23c684c4f6 %}

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:

{% gist https://gist.github.com/hunterbecton/c94cbe332cd743c3a4c8d229dc04886b %}

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:

{% gist https://gist.github.com/hunterbecton/13b9f56e79ba98f6409f63ccd2836ee6 %}

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:

{% gist https://gist.github.com/hunterbecton/0b5ff6f5e4f98da58114a90af4b95cb9 %}

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](https://www.youtube.com/channel/UCvHKiUI75ytqUcN851fRR2w). And as always, if you have any questions feel free to drop them below.