首页 > 解决方案 > 如何使用包装器控制按钮的切换

问题描述

我正在构建一个切换按钮,规范告诉我一组切换按钮应该具有只允许单击(参见示例)和多次单击(参见示例)的行为。

多次单击很好,因为没有太多逻辑要实现,但是单击对我来说很难。使用单击的主要思想是,如果我切换一个按钮并尝试切换另一个按钮,前一个应该失去他的状态,pressed而被点击的那个应该有它。当pressed为 true 时,ToggleButton 具有不同的 CSS。

这是我的切换按钮组件:

const ToggleButton = props => {
  const { onClick, value, ...other } = props;
  const [pressed, setPressed] = useState(true);
  const renderPressedButton = () => {
    setPressed(!pressed);
    if (onClick) {
      onClick();
    }
  };
  return (
    <StyledToggleButton
      className={!pressed ? 'pressed' : null}
      pressed={pressed}
      data-value={value}
      {...other}
      onClick={renderPressedButton}
    />
  );
};

这是我的包装器(atm 我只得到我点击的类):

const onClickHandler = e => {
  const index = e.target.closest('.pressed');
  // console.log(index);
  // console.log('classe: ', e.target.className);
  if (index) {
    console.log('its pressed!');
  }
};

const ToggleButtonGroup = props => {
  const { ...other } = props;
  return <StyledToggleButtonGroup onClick={onClickHandler} {...other} />;
};

我认为我应该使用 Context API 或者将我的renderPressedButton逻辑移动到我的包装器中。有人有想法吗?

这就是我计划使用该组件的方式:

<ToggleButtonGroup singleClick>
     <ToggleButton>One</ToggleButton>
     <ToggleButton>Two</ToggleButton>
</ToggleButtonGroup>

标签: javascriptreactjs

解决方案


将状态提升至ToggleButtonGroup。在那里维护一个切换索引的列表,并提供一个布尔值作为道具来ToggleButton保持它完全无状态。通过这种方式,您将能够根据任何点击ToggleButton单独控制每个。ToggleButtonGroup

function ToggleButtonGroup({ singleClick, children }) {
  const [checked, setChecked] = React.useState([]);

  const handleClick = event => {
    // event.target should have your clicked checbox reference
    const index = event.target.dataset.index;

    if (singleClick) {
      setChecked([index]);
    } else {
      if (checked.includes(index)) {
        setChecked(checked.filter(eachIndex => eachIndex !== index));
      } else {
        setChecked([...checked, index]);
      }
    }
  };

  return (
    <div onClick={handleClick}>
      {React.Children.map(children, (child, index) => {
        return React.cloneElement(child, {
          dataIndex: index,
          pressed: checked.includes(index)
        });
      })}
    </div>
  );
}



function ToggleButton({ dataIndex, pressed, ...rest }) {
  return <div data-index={dataIndex} className={!pressed ? 'pressed' : null} {...rest} />;
}

推荐阅读