DEV Community

loading...
Cover image for Project 84 of 100 - Accordion style FAQs page

Project 84 of 100 - Accordion style FAQs page

James Hubert
Customer experience-centric product lover and front-end developer in New York. Follow my dev Twitter: www.twitter.com/jwhubert91
・3 min read

Hey! I'm on a mission to make 100 React.js projects. Please follow my dev.to profile or my twitter for updates and feel free to reach out if you have questions. Thanks for your support!

Link to today's deployed app: Link
Link to the repo: github

This is part 4 of 15 in a series on building React projects by John Smilga, covered in this 10 hour video on Youtube.

Today could be seen as a recap of previously learned knowledge from John Smilga's course. We tackle functional components, passing props, state and the useState hook, conditional rendering, and basic JSX.

Since if you've been following along with my blog posts throughout the 100 days project, or just with the John Smilga projects over the last few posts, you know all of the above, I'll just go over the onClick functionality that governs the open / shut accordion effect for these FAQ questions.

First, to set up the project we pull in the JSON data from our local data.js file. The objects in that file look like the following:

  {
    id: 1,
    title: 'Do I have to allow the use of cookies?',
    info:
      'Unicorn vinyl poutine brooklyn, next level direct trade iceland. Shaman copper mug church-key coloring book, whatever poutine normcore fixie cred kickstarter post-ironic street art.',
  }
Enter fullscreen mode Exit fullscreen mode

To actually pull that data in, we don't bother with useEffect this time. Since the data is local we can just pull it in directly from its default export, and save it as the default state for a questions variable in App.js like so:

import React, { useState } from 'react';
import data from './data';

function App() {
  const [questions,setQuestions] = useState(data)
  ...
}
Enter fullscreen mode Exit fullscreen mode

Now in the return for App.js we set up a super basic page so that we can iterate through our questions and render a Question component for each question from data.js.

Side note: I kind of like how all of John Smilga's returns in React functional components don't use parentheses. Like I get that you don't need them, but for some reason I just feel insecure with out them. It does look a little cleaner though with them in my opinion, but maybe this is more concise. I also like how he regularly destructures object properties as props by simple placing the destructured object in curly brackets as a prop while calling a component.

return <main>
    <div className='container'>
      <h3>questions and answers about login</h3>
      <section className='info'>
        {
          questions.map((question) => {
            return <SingleQuestion key={question.id} {...question} />
          })
        }
      </section>
    </div>
  </main>;
Enter fullscreen mode Exit fullscreen mode

Now in the SingleQuestion component we destructure the props, which we know from the data.js file, then set up some JSX to display the data.

const Question = ({title,info}) => {

  return <article className='question'>
    <header>
      <h4>{title}</h4>
      <button className='btn'>
      </button>
    </header>
    <p>{info}</p>
  </article>;
};
Enter fullscreen mode Exit fullscreen mode

Now we've got components listed and showing data, but we don't have the accordion functionality, and our buttons don't say anything. To achieve the accordion functionality we need a piece of state on each question's component to keep track of whether it's open or closed. Then we'll need to conditionally render the info text if the state variable true or false.

const Question = ({title,info}) => {
  const [showInfo,setShowInfo] = useState(false)

  return <article className='question'>
    <header>
      <h4>{title}</h4>
      <button className='btn'>
      </button>
    </header>
    {showInfo && <p>{info}</p>}
  </article>;
};
Enter fullscreen mode Exit fullscreen mode

Finally, we add conditional rendering to show a different icon (from the react-icons npm package) to the user based on the value of the showInfo state variable. An onClick method toggles the state variable's truthiness.

      <button className='btn' onClick={() => setShowInfo(!showInfo)}>
        {showInfo ? <AiOutlineMinus /> : <AiOutlinePlus />}
      </button>
Enter fullscreen mode Exit fullscreen mode

That wraps up this one. It's an easy project and entirely review, but I think it's great to have an accordion project in your pocket (and portfolio). Chances are if you go front-end, you'll need to build one of these at some point. And even if not, it's a good review of some of the most fundamental principles of modern React: JSX, functional components, , iteration, conditional rendering, and the useState hook.

If you like projects like this and want to stay up to date with more, check out my Twitter @jwhubert91, I follow back! See you tomorrow for another project.

Discussion (0)