Home > Net >  selecting each individual button from the to toggle a css class but when I do only the last item in
selecting each individual button from the to toggle a css class but when I do only the last item in

Time:05-05

The following is the code for my component

import React from 'react'
import Wrapper from '../../assets/css/LandingPageSmallerSectionCss/faqSectioncss'
// import FaqComponent from '../../components/faqComponent'
import faqs from '../../utils/faqs'

const FaqSection = () => {
    const ref = React.createRef();
    const toggleHandler = (e) => {
         e.preventDefault()
         ref.current.classList.toggle('.show-more')
     }
    return (
        <Wrapper>
            <div className="faq-container">
                <h1 className="faqs-header" style={{ color: "rgb(40, 102, 129)" }}>FAQs</h1>
                <div className="list-container">
                    <ul>
                        {faqs.map((faq) => {
                            const { id, question, answer } = faq
                            return (
                                <li key={id}>
                                    <p>{question}</p>
                                    <button className="toggle-more-btn" onClick={toggleHandler}></button>
                                    <p className="faq-text" ref={ref}>{answer}</p>
                                </li>
                            )
                        })}
                    </ul>
                </div>
            </div>
        </Wrapper>
    )
}

export default FaqSection

I can implement the code for toggling in pure javascript and plain html but i'm having trouble translating it to react since react does not have queryselectorAll hence i'm having trouble,the following is the code for the pure javascript

let listContent= document.querySelectorAll('.faq-text')
let buttonContent = document.querySelectorAll('.toggle-more-btn')
const listArray=Array.from(listContent)
const buttonArray=Array.from(buttonContent)

//display both array list

// console.log(listArray)
// console.log(buttonArray)

//check if individual examples buttons are coherent with each other

// if (buttonArray[0] && listArray[0]) {
//     buttonArray[0].addEventListener('click',(e)=>{
//         listArray[0].classList.toggle('poopoo')
//     })
// }
// if (buttonArray[1] && listArray[1]) {
//     buttonArray[1].addEventListener('click',(e)=>{
//         listArray[1].classList.toggle('poopoo')
//     })
// }

//loop through all buttons in the list and if both the index of the button and list match
// for (let i = 0; i < buttonArray.length; i  ) {
//     if (buttonArray[i]&&listArray[i]) {
//      buttonArray[i].addEventListener('click',e=>{
//      listArray[i].classList.toggle('poopoo')
//        })}   
// }


// create funcion that works with individual array indexes
//experimental

const buttonPress=(button,list)=>{
    for (let i = 0; i < button.length; i  ) {
        if (button[i]&&list[i]) {
            button[i].addEventListener('click',e=>{
                list[i].classList.toggle('show-more')
                button[i].classList.toggle('rotate-btn')
            })
        }
    }
}
buttonPress(buttonArray,listArray)

I've spent hours on this. If anyone could answer me i'd be greatfull,kindly?

CodePudding user response:

It is a couple things so far:

  1. Handler function is not named the same as what is called.
  2. The DOT on your css class .show-more! It took awhile (and a console.log to find this).
  3. I don't think you want a ref in the first place.

Here is what I might do using some hooks. I'm faking first load with the useEffect, with empty array arg. Then, I'm going to set the changed faq entry in a clone of the list "faqs", and then spread my temp array into the setFaqs. This is using the useState hook, which generally you give a variable name and then a setter function name (and for these built-ins React takes care of actually setting up in the background - including the default I have an empty array).

import { useEffect, useState } from "react";
import "./styles.css";

const mockServerReturn = [
  { id: 0, question: "Foo?", answer: "Bar!" },
  { id: 1, question: "Baz?", answer: "Bar!" },
  { id: 2, question: "Bar?", answer: "Bar!" }
];

const FaqSection = () => {
  const [faqs, setFaqs] = useState([]);

  useEffect(() => setFaqs(mockServerReturn), []);

  const toggleHandler = (e) => {
    e.preventDefault();
    const temp = [...faqs];
    temp[e.target.id].chosen = !temp[e.target.id].chosen;
    setFaqs([...temp]);
  };

  return (
    <>
      <div className="faq-container">
        <h1 className="faqs-header">FAQs</h1>
        <div className="list-container">
          <ul>
            {faqs.map((faq) => {
              const { id, question, answer, chosen } = faq;
              return (
                <li key={id}>
                  <p>{question}</p>
                  <button
                    className="toggle-more-btn"
                    onClick={toggleHandler}
                    id={id}
                  >
                    I choose {id}
                  </button>
                  <p className={`faq-text${chosen ? " show-more" : ""}`}>
                    {id}:{answer}:{chosen?.toString()}
                  </p>
                </li>
              );
            })}
          </ul>
        </div>
      </div>
    </>
  );
};

export default function App() {
  return (
    <div className="App">
      <FaqSection />
    </div>
  );
}
  • Related