skip to Main Content

I have an activeBtn function to set an activeLink class when the button is clicked. In this case, i want to remove the state of the other buttons to false when it isn’t clicked. So i only have one active button at a time. i don’t know how to select the elements on react. i usually use document.querySelector().classList.add() or remove to do this. how to do it on react?

import React, { useState } from 'react';

const Button = ({ text, data }) => {
  const [isActive, setIsActive] = useState(false);
  const activeBtn = () => {
    setIsActive(true)
  }
  const activeLink = 'bg-light-one text-main-color text-light-one rounded-[2rem] border-none outline-none my-[0.45rem] mx-[0.4rem] py-[0.85rem] px-[1.8rem] uppercase font-medium leading-none cursor-pointer transition duration-300';
  const normalLink = 'text-lg bg-transparent text-light-one rounded-[2rem] border-none outline-none my-[0.45rem] mx-[0.4rem] py-[0.85rem] px-[1.8rem] uppercase font-medium leading-none cursor-pointer transition duration-300';
  return (
    <button onClick={activeBtn} type='button' data-filter={data} className={isActive ? activeLink : normalLink}>
      {text}
    </button>
  );
};

export default Button;

i tried useRef but idk how to properly use it and set the state to false

2

Answers


  1. There can be various approaches according to the exact requirements (which are not quite clear from your question).

    Here is one simple approach to have only one active button at a time.

    You will need to lift the state up to a parent component that contains the buttons. This state will keep track of the active button based on some unique value or property of that button (in this example, I’ve used a unique text value). You will need to pass both the active state to the button as well as the setter method, in order for the buttons to be able to set the parent state and update the view with the last active button.

    const Button = ({ text, active, setActive }) => {
      return (
        <button
          onClick={() => setActive(text)}
          style={active === text ? { background: "green" } : { background: "red" }}
        >
          {text}
        </button>
      );
    };
    
    export default function App() {
      const [active, setActive] = useState(false);
      return (
        <>
          <Button active={active} setActive={setActive} text="A" />
          <Button active={active} setActive={setActive} text="B" />
          <Button active={active} setActive={setActive} text="C" />
        </>
      );
    }
    

    Depending on your setup, you can also map over the Button elements or use the Context API to share the active, setActive state with these Button Components.

    Login or Signup to reply.
  2. you can use an array collect all the buttons status and by the data to drive the UI render like this:

    interface IButtonStatus {
            name: string
            active: boolean
            text: string
        }
        const initButtonsStatus: IButtonStatus[] = [{ name: 'btn1', active: false, text: 'button1' }, { name: 'btn2', active: false, text: 'button2' }];
        const [buttonsStatus, setButtonsStatus] = useState<IButtonStatus[]>(initButtonsStatus);
    
        const activeBtn = (name: string) => {
            const curButtonsStatus = [...buttonsStatus]
            curButtonsStatus.forEach(item => {
                if (item.name === name) {
                    item.active = true
                } else {
                    item.active = false
                }
            })
            setButtonsStatus(curButtonsStatus);
        }
    
        const checkStatus = (buttonName: string, buttonsStatus: IButtonStatus[]) => {
            const buttonItem = buttonsStatus.find((item: IButtonStatus) => item.name === buttonName)
            return buttonItem && buttonItem.active ? "active" : "normal"
        }
    
        return (
            <div>
                {
                    buttonsStatus.map((item: IButtonStatus) => {
                        return <button key={item.name}
                            onClick={() => activeBtn(item.name)}
                            className={checkStatus(item.name, buttonsStatus)}>{item.text}</button>
                    })
                }
            </div>
        )
    

    I use TypeScript, you can remove the type declarations.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search