如何在React中选择多个元素并将状态设置为false

huangapple go评论69阅读模式
英文:

How to select multiple elements in react and set a state to false

问题

我有一个activeBtn函数,用于在点击按钮时设置activeLink类。在这种情况下,我想在按钮未被点击时将其他按钮的状态设置为false,以便一次只有一个活动按钮。我不知道如何在React中选择元素。我通常使用document.querySelector().classList.add()或remove来实现这一点。在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;

我尝试过使用useRef,但不知道如何正确使用它来将状态设置为false。

英文:

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 &#39;react&#39;;

const Button = ({ text, data }) =&gt; {
  const [isActive, setIsActive] = useState(false);
  const activeBtn = () =&gt; {
    setIsActive(true)
  }
  const activeLink = &#39;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&#39;;
  const normalLink = &#39;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&#39;;
  return (
    &lt;button onClick={activeBtn} type=&#39;button&#39; data-filter={data} className={isActive ? activeLink : normalLink}&gt;
      {text}
    &lt;/button&gt;
  );
};

export default Button;

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

答案1

得分: 0

根据确切的要求可以有不同的方法(从你的问题中并不太清楚)。以下是一种简单的方法,一次只允许一个按钮处于活动状态。

你需要将状态提升到包含按钮的父组件中。这个状态将根据按钮的某个唯一值或属性(在这个示例中,我使用了唯一的 text 值)来跟踪活动按钮。你需要将 active 状态和设置方法都传递给按钮,以便按钮能够设置父级状态并更新视图以显示最后一个活动按钮。

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" />
    </>
  );
}

根据你的设置,你也可以使用 map 方法遍历按钮元素,或者使用 Context API 来与这些按钮组件共享 active, setActive 状态。

英文:

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 }) =&gt; {
  return (
    &lt;button
      onClick={() =&gt; setActive(text)}
      style={active === text ? { background: &quot;green&quot; } : { background: &quot;red&quot; }}
    &gt;
      {text}
    &lt;/button&gt;
  );
};

export default function App() {
  const [active, setActive] = useState(false);
  return (
    &lt;&gt;
      &lt;Button active={active} setActive={setActive} text=&quot;A&quot; /&gt;
      &lt;Button active={active} setActive={setActive} text=&quot;B&quot; /&gt;
      &lt;Button active={active} setActive={setActive} text=&quot;C&quot; /&gt;
    &lt;/&gt;
  );
}

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.

答案2

得分: -1

你可以使用一个数组来收集所有按钮的状态,并根据数据来驱动 UI 渲染,代码如下:

const initButtonsStatus = [{ name: 'btn1', active: false, text: 'button1' }, { name: 'btn2', active: false, text: 'button2' }];
const [buttonsStatus, setButtonsStatus] = useState(initButtonsStatus);

const activeBtn = (name) => {
    const curButtonsStatus = [...buttonsStatus];
    curButtonsStatus.forEach(item => {
        if (item.name === name) {
            item.active = true;
        } else {
            item.active = false;
        }
    });
    setButtonsStatus(curButtonsStatus);
};

const checkStatus = (buttonName, buttonsStatus) => {
    const buttonItem = buttonsStatus.find(item => item.name === buttonName);
    return buttonItem && buttonItem.active ? "active" : "normal";
};

return (
    <div>
        {
            buttonsStatus.map(item => {
                return <button key={item.name}
                    onClick={() => activeBtn(item.name)}
                    className={checkStatus(item.name, buttonsStatus)}>{item.text}</button>;
            })
        }
    </div>
);

我使用了 TypeScript,你可以移除类型声明部分。

英文:

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: &#39;btn1&#39;, active: false, text: &#39;button1&#39; }, { name: &#39;btn2&#39;, active: false, text: &#39;button2&#39; }];
    const [buttonsStatus, setButtonsStatus] = useState&lt;IButtonStatus[]&gt;(initButtonsStatus);

    const activeBtn = (name: string) =&gt; {
        const curButtonsStatus = [...buttonsStatus]
        curButtonsStatus.forEach(item =&gt; {
            if (item.name === name) {
                item.active = true
            } else {
                item.active = false
            }
        })
        setButtonsStatus(curButtonsStatus);
    }

    const checkStatus = (buttonName: string, buttonsStatus: IButtonStatus[]) =&gt; {
        const buttonItem = buttonsStatus.find((item: IButtonStatus) =&gt; item.name === buttonName)
        return buttonItem &amp;&amp; buttonItem.active ? &quot;active&quot; : &quot;normal&quot;
    }

    return (
        &lt;div&gt;
            {
                buttonsStatus.map((item: IButtonStatus) =&gt; {
                    return &lt;button key={item.name}
                        onClick={() =&gt; activeBtn(item.name)}
                        className={checkStatus(item.name, buttonsStatus)}&gt;{item.text}&lt;/button&gt;
                })
            }
        &lt;/div&gt;
    )

I use TypeScript, you can remove the type declarations.

huangapple
  • 本文由 发表于 2023年2月27日 08:31:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575899.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定