在React中创建按钮的多选网格

时间:2019-06-05 15:06:10

标签: javascript reactjs

size side bar

我试图在具有以上外观的React.js中实现按钮网格。

预期行为

单击每个按钮可切换selected上的SizeButton类。

上图中选择的按钮是带有'X'的按钮。

实际上发生了什么

单击每个按钮不会会在selected上切换SizeButton类。

我相信实现的方式是一个包装组件,其中包含许多单独的按钮组件。包装组件将包含与每个按钮的状态有关的状态信息。

上面的图片是我所期望的,但实际上并没有发生。

SizeSideBar.js

class SizeSideBar extends Component {
    constructor(props) {
        super(props);

        this.state = {
            query: ''
        }

        this.setSize = this.setSize.bind(this);
    }

    setSize(size) {
        this.setState({
            query: size.toUpperCase(),
        }, () => {
            if (this.state.query.length > 0) {
                this.props.history.push(`?size=${size.toUpperCase()}`)
            }
        })
    }

    render() {
        return (
            <div>
                <h3>Size</h3>
                <hr />
                <div>
                    <SizeButton size="x" setSize={this.setSize} />
                    <SizeButton size="xxs" setSize={this.setSize} />
                    <SizeButton size="xs" setSize={this.setSize} />
                    <SizeButton size="s" setSize={this.setSize} />
                    <SizeButton size="m" setSize={this.setSize} />
                    <SizeButton size="l" setSize={this.setSize} />
                    <SizeButton size="xl" setSize={this.setSize} />
                    <SizeButton size="xxl" setSize={this.setSize} />
                    <SizeButton size="2xl" setSize={this.setSize} />
                    <SizeButton size="3xl" setSize={this.setSize} />
                    <SizeButton size="4xl" setSize={this.setSize} />
                </div>
            </div>
        )
    }
}

SizeButton.js

const SizeButton = (props) => {
    const { size, setSize } = props

    const selectedSize = getPageQueries(window.location.search).size
    const isSelected = selectedSize === size

    return (
        <button
            id="sizeButton"
            className={isSelected ? 'selected' : ''}
            onClick={() => {
                setSize(size);
            }}
        >
            {size.toUpperCase()}
        </button>
    )
}

getPageQueries()

export const getPageQueries = (url) => {
    const arr = url.slice(1).split(/&|=/); // remove the "?", "&" and "="
    let params = {};

    for(let i = 0; i < arr.length; i += 2){
       const key = arr[i], value = arr[i + 1];
       params[key] = value ; // build the object = { limit: "10", page:"1", status:"APPROVED" }
    }

    return params;
};

1 个答案:

答案 0 :(得分:2)

让每个按钮管理其自己的选定状态,单击时将设置其自己的颜色。

class SizeButton extends React.Component {

  state = {
    isSelected: false,
  }

  setSelected = () => {
    this.setState({
      isSelected: !this.state.isSelected
    })
  }

  render() {
    const { size, setSize } = this.props;
    return (
      <button
        id="sizeButton"
        className={this.state.isSelected ? 'selected' : ''}
        onClick={() => {
          this.setSelected();
          setSize(size);
        }}
      >
        {size.toUpperCase()}
      </button>
    )
  }
}

OR

创建一个尺寸对象数组,例如{size: 'X', isSelected: false },并循环遍历该数组,检查isSelected是否为真。

state = {
 query: [
   {size: 'X', isSelected: false },
   {size: 'xxs', isSelected: false },
   {size: 'xs', isSelected: false }
 ],
}

然后渲染类似的尺寸

render() {
  return (
    <div>
      <h3>Size</h3>
      <hr />
      <div />
      {this.state.queries.map((button, key) => (
        <SizeButton
          key={key}
          size={button.size}
          isSelected={button.isSelected}
          setSize={this.setSize}
        />
      ))}
    </div>
  );
}


const SizeButton = (props) => {
const { size, setSize, isSelected } = props

  return (
      <button
        id="sizeButton"
        className={isSelected ? 'selected' : ''}
        onClick={() => {
            setSize(size);
        }}
      >
        {size.toUpperCase()}
      </button>
   )
}

演示

.selected {
  border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>

<script type="text/babel">

class SizeButton extends React.Component {

  state = {
    isSelected: false,
  }

  setSelected = () => {
    this.setState({
      isSelected: !this.state.isSelected
    })
  }

  render() {
    const { size, setSize } = this.props;
    return (
      <button
        id="sizeButton"
        className={this.state.isSelected ? 'selected' : ''}
        onClick={() => {
          this.setSelected();
          setSize(size);
        }}
      >
        {size.toUpperCase()}
      </button>
    )
  }
}

class App extends React.Component {

  state = {

  }

  setSize = (size) => {

  }

  render() {
    return (
      <div>
        <h3>Size</h3>
        <hr />
        <div>
          <SizeButton size="x" setSize={this.setSize} />
          <SizeButton size="xxs" setSize={this.setSize} />
          <SizeButton size="xs" setSize={this.setSize} />
          <SizeButton size="s" setSize={this.setSize} />
          <SizeButton size="m" setSize={this.setSize} />
          <SizeButton size="l" setSize={this.setSize} />
          <SizeButton size="xl" setSize={this.setSize} />
          <SizeButton size="xxl" setSize={this.setSize} />
          <SizeButton size="2xl" setSize={this.setSize} />
          <SizeButton size="3xl" setSize={this.setSize} />
          <SizeButton size="4xl" setSize={this.setSize} />
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

</script>