React useState切换单个按钮

时间:2020-04-21 11:12:56

标签: javascript reactjs

我在react组件中有多个按钮,这些按钮使我可以根据单击的按钮来显示或隐藏一些数据。我有一个切换动画,它将设置两个不同的图标状态(显示和隐藏)

设置状态

这是我设置状态的方法:const [clicked, setClicked] = useState(false);

处理点击

切换点击事件的功能

  const handleClick = () => {
    setClicked(s => !s);
  };

按钮切换

          <Button className={style.selector} onClick={handleClick}>
            {clicked ? (
              <img src={off} alt="hidden" />
            ) : (
              <img src={on} alt="visible" />
            )}
            {
              <FormattedMessage
                id="side_properties"
                defaultMessage={"BUTTON 1"}
              />
            }
          </Button>

      // other buttons below with the same format.

切换图标功能有效,但是单击单个按钮时,其余所有按钮上的图标都会更改。如何将此点击事件限制为单个按钮?

4 个答案:

答案 0 :(得分:1)

您应该跟踪state中每个button的{​​{1}},并分别更新每个按钮。

这是一个可能的解决方案:

array

如果您想看看,这是一个工作示例:

答案 1 :(得分:0)

我认为您需要为您的状态定义某种枚举:

const btnState = {
  normal: 0,
  btn1Clicked: 1,
  btn2Clicked: 2,
}

然后像这样在您的状态下使用:

const [clicked, setClicked] = useState(btnState.normal);

您的按钮将如下所示:

          <Button className={style.selector} onClick={e => handleClick(btnState.btn1Clicked)}>
            {clicked === btnState.btn1Clicked ? (
              <img src={off} alt="hidden" />
            ) : (
              <img src={on} alt="visible" />
            )}
            {
              <FormattedMessage
                id="side_properties"
                defaultMessage={"BUTTON 1"}
              />
            }
          </Button>

和您的handleClick像这样:

  const handleClick = (state) => {
    setClicked(state);
  };

答案 2 :(得分:0)

听起来像您对所有按钮使用相同的状态。您将分别需要每个按钮的状态。

const [button1Clicked, setButton1Clicked] = useState(false);
const [button2Clicked, setButton2Clicked] = useState(false);
...

然后为每个按钮

          <Button className={style.selector} onClick={() => setButton1Clicked(s => !s);}>
            {clicked ? (
              <img src={off} alt="hidden" />
            ) : (
              <img src={on} alt="visible" />
            )}
            {
              <FormattedMessage
                id="side_properties"
                defaultMessage={"BUTTON 1"}
              />
            }
          </Button>

您也可以使用对象或数组作为状态,而不是每个按钮都具有一个变量。

const buttons = ['button1', 'button2',...] //Consider using meaningful names here
const [buttonStates, setButtonStates] = useState(buttons.reduce((accum, currVal) => ({
  ...accum,
  [currVal]: false
}), {}));

const handleClick = (buttonName) => {
  setClicked(s => ({
    ...s,
    [buttonName]: !s[buttonName]
  })); 
};

然后为每个按钮

          <Button className={style.selector} onClick={() => handleClick('button1')}>
            {clicked ? (
              <img src={off} alt="hidden" />
            ) : (
              <img src={on} alt="visible" />
            )}
            {
              <FormattedMessage
                id="side_properties"
                defaultMessage={"BUTTON 1"}
              />
            }
          </Button>

请注意,您应该将“ button1”更改为每个按钮的名称。

答案 3 :(得分:0)

这是因为您的所有按钮文本都基于一个状态变量。有多种解决方法。 如果您一次只想要一个活动按钮:

const buttonMap = {
    button1: 'button1',
    button2: 'button2',
}

const [clicked, setClicked] = useState(); // Default button which you want to be clicked

const handleClick = (button) => {
    setClicked(button);
};

<Button 
     onClick={e => handleClick(buttonMap.button1)}
>
    {
        clicked === buttonMap.button1 ? (
          <img src={off} alt="hidden" />
        ) : (
          <img src={on} alt="visible" />
        )
    }

</Button>

如果您希望一次激活多个按钮...您需要为每个按钮使用不同的状态属性...为此,您可以为每个按钮使用多个状态变量,或者可以为该状态使用一个对象该对象的键将通知按钮是否被单击。

const intialButtonState = {
    button1: false,
    button2: false,
}

const [clicked, setClicked] = useState(intialButtonState); // Default button which you want to be clicked

const handleClick = (button) => {
    setClicked({...clicked, [button]: !clicked[button]});
};

<Button 
     onClick={e => handleClick('button1')}
>
    {
        clicked.button1 ? (
          <img src={off} alt="hidden" />
        ) : (
          <img src={on} alt="visible" />
        )
    }

</Button>