React:通过按钮点击

时间:2017-08-15 10:59:05

标签: javascript reactjs

我有一个组件可以呈现三个自定义单选按钮。用户可以提交所选内容或清除(取消选择)它们,而不选择任何单选按钮。

我尝试了将filterResultdata.value进行比较的一些选项,但没有成功。这是一个简化的代码:

// imports
...

type Props = {
  filterConfig: PropTypes.object,
  filterValue: Proptypes.string,
  onFilterChange: PropTypes.func
}

class Filter extends React.Component {
  this.props = Props
  this.state = {
    filterValue: this.props.filterValue,
  }

  handleChange = (e) => {
    this.setState({ filterValue: e.target.value })
  }

  handleSubmit = () => {
    this.props.onFilterChange(this.state.filterValue)
    this.refs.filterContainer.close()
  }

  handleClear = () => {
    this.setState({ filterValue: '' })
  }

  renderOptions = () => {
    const { data, name } = this.props.filterConfig
    const options = data.map(
      (o, i) => (
        <div className='custom-radio' key={i}>
          <input
            id={`${name}-${i}`}
            name={name}
            onChange={this.handleChange}
            type='radio'
            value={o.value}
          />
          <label htmlFor={`${name}-${i}`}>
            <span />
            {o.label}
          </label>
        </div>
      )
    )

    return (
      <div>
        {options}
      </div>
    )
  }

  renderPickerNavigation = () => {
    return (
      <div>
        <a
          href='javascript:void(0)'
          onClick={this.handleClear}
        >
          Clear
        </a>
        <a
          href='javascript:void(0)'
          onClick={this.handleSubmit}
        >
          Done
        </a>
      </div>
    )
  }

  render = () => {
    return (
      <FilterWrapper
        ref='filterWrapper'
      >
        {this.renderOptions()}
        {this.renderPickerNavigation()}
      </FilterWrapper>
    )
  }
}

我传入的数据是:

const filters = [
  {
    data: [{
      label: 'Label 1',
      value: 1
    }, {
      label: 'Label 2',
      value: 2
    }, {
      label: 'Label 3',
      value: 3
    }],
    name: 'userFilter'
  }
]

编辑:原生广播输入上的点击事件工作正常,因此无需将其更改为自定义广播(span元素)或标签。

2 个答案:

答案 0 :(得分:2)

首先应该有一个状态变量来存储当前选择的无线电。如果您不想预先选择任何一个,则初始值应为null(或其他一些假值)。

重置按钮应触发一个功能,将该状态变量重置为初始值。

根据您的要求,使用自定义css单选按钮查看这个简单的演示:

class MyApp extends React.Component {
  constructor() {
    super();
    this.state = {
      selectedRadio: null,
      products: [{id: 1, name: "foo"}, {id: 2, name: "bar"}, {id: 3, name: "baz"}]
    }
  }
  
  select = (id) => {
    this.setState({selectedRadio: id});
  }
  
  reset = () => {
    this.setState({selectedRadio: null});
  }
  
  render() {
    return (
      <div>
        {this.state.products.map(
          (item) => {
            return (
              <div key={item.id}>
                <input type="radio" name="myRadio" checked={this.state.selectedRadio === item.id} />
                <label onClick={this.select.bind(this, item.id)}>{item.name}<span /></label>
              </div>
            );
          }
        )}
        <button onClick={this.reset}>Reset</button>
      </div>
    );
  }
}

ReactDOM.render(<MyApp />, document.getElementById("app"));
div {
  margin: 10px 0;
}

input[type="radio"] {
  display: none;
}

input[type="radio"]+label span {
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-left: 4px;
  vertical-align: middle;
  cursor: pointer;
  border-radius: 34%;
}

input[type="radio"]+label span {
  background-color: #333;
}

input[type="radio"]:checked+label span {
  background-color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

注意: 由于您使用css隐藏了输入元素,因此您无法使用任何侦听器(例如onChange或{{1 }})。相反,您应该onClick替换它onClick(请参阅下面的代码)。

有关如何重置所有“传统”,非css专用单选按钮的解决方案,请参阅下面的代码段:

span
class MyApp extends React.Component {
  constructor() {
    super();
    this.state = {
      selectedRadio: null,
      products: [{id: 1, name: "foo"}, {id: 2, name: "bar"}, {id: 3, name: "baz"}]
    }
  }
  
  select = (id) => {
    this.setState({selectedRadio: id});
  }
  
  reset = () => {
    this.setState({selectedRadio: null});
  }
  
  render() {
    return (
      <div>
        {this.state.products.map(
          (item) => {
            return (
              <div key={item.id}>
                <label>{item.name}</label>
                <input type="radio" name="myRadio" onChange={this.select.bind(this, item.id)} checked={this.state.selectedRadio === item.id} />
              </div>
            );
          }
        )}
        <button onClick={this.reset}>Reset</button>
      </div>
    );
  }
}

ReactDOM.render(<MyApp />, document.getElementById("app"));

答案 1 :(得分:0)

此示例可以帮助您https://codepen.io/evoyan/pen/vxGBOw

代码:

class Radio extends React.Component {
  constructor(props) {
    super(props);
    this.state = {selected: false};
  }

  toggle() {
    const {onChange} = this.context.radioGroup;
    const selected = !this.state.selected;
    this.setState({selected});
    onChange(selected, this);
  }

  setSelected(selected) {
    this.setState({selected});
  }

  render() {
    let classname = this.state.selected ? 'active' : ''
    return (
      <button type="button" className={classname} onClick={this.toggle.bind(this)}>
        {this.state.selected ? 'yes' : 'no'}
      </button>
    );
  }
}

Radio.contextTypes = {
  radioGroup: React.PropTypes.object
};

class RadioGroup extends React.Component {
  constructor(props) {
    super(props);
    this.options = [];
  }

  getChildContext() {
    const {name} = this.props;
    return {radioGroup: {
      name,
      onChange: this.onChange.bind(this)
    }};
  }

  onChange(selected, child) {
    this.options.forEach(option => {
      if (option !== child) {
        option.setSelected(!selected);
      }
    });
  }

  render() {
    let children = React.Children.map(this.props.children, child => {
      return React.cloneElement(child, {
        ref: (component => {this.options.push(component);}) 
      });
    });
    return <div className="radio-group">{children}</div>;
  }
}

RadioGroup.childContextTypes = {
  radioGroup: React.PropTypes.object
};

class Application extends React.Component {
  render() {
    return (
      <RadioGroup name="test">
        <Radio value="1" />
        <Radio value="2" />
        <Radio value="3" />
      </RadioGroup>
    );
  }
}

/*
 * Render the above component into the div#app
 */
ReactDOM.render(<Application />, document.getElementById('app'));