How to get values/properties from a react-bootstra

2019-06-22 20:33发布

问题:

I'm trying to use the react-bootstrap checkbox (https://react-bootstrap.github.io/components.html#forms-controls) and I need to fire an event when it changes state. It would also be great to be able to programatically un/check it and/or tell if it is checked. Unfortunately when the code is transpiled and rendered it wraps the input in a div.

How can I find this in the dom and manipulate it?

My code looks similar to this:

import React, { PropTypes } from 'react';
import { Checkbox } from 'react-bootstrap';

const EditItem = (props) => {

  return (
    <div>
      <Checkbox style={{ marginLeft: '15px' }} >{props.itemLable}</Checkbox>
    </div>
  );
};

export default EditItem;

And the browser renders this:

...
<div class="checkbox" style="margin-left: 15px;">
  <label>
    <input type="checkbox">
  </label>
</div>
...

I see the inputRef prop in the documentation but I can't find any examples of this or get it to work myself.

回答1:

There are two ways: The React way and the not-so-React way.

The React way is to set the child component's state by passing it props and respond to changes in its state by attaching event handlers. In the case of Checkbox, that means setting the checked and onChange props.

Note in the below example how the parent component (App) keeps track of the Checkbox's state and can both set it with this.setState and query it with this.state.checkboxChecked.

const { Checkbox, Button } = ReactBootstrap;

class App extends React.Component {
  constructor() {
    super();
    this.state = { checkboxChecked: false };
    this.handleChange = this.handleChange.bind(this);
    this.handleIsItChecked = this.handleIsItChecked.bind(this);
    this.handleToggle = this.handleToggle.bind(this);
  }
  
  render() {
    return (
      <div>
        <Checkbox
          checked={this.state.checkboxChecked}
          onChange={this.handleChange} />
        <Button type="button" onClick={this.handleToggle}>Toggle</Button>
        <Button type="button" onClick={this.handleIsItChecked}>Is it checked?</Button>
      </div>
    );
  }
  
  handleChange(evt) {
    this.setState({ checkboxChecked: evt.target.checked });
  }
  
  handleIsItChecked() {
    console.log(this.state.checkboxChecked ? 'Yes' : 'No');
  }
  
  handleToggle() {
    this.setState({ checkboxChecked: !this.state.checkboxChecked });
  }
}

ReactDOM.render(<App/>, document.querySelector('div'));
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react-bootstrap/0.30.8/react-bootstrap.min.js"></script>
<div></div>

The not-so-React way is to get a reference to the rendered DOM element and access its checked property directly. I don't recommend this, because it necessarily pollutes your lovely functional React code with icky imperative code. Nevertheless, with React-Bootstrap you can do it by setting the inputRef prop, as in the below example:

const { Checkbox, Button } = ReactBootstrap;

class App extends React.Component {
  constructor() {
    super();
    this.handleIsItChecked = this.handleIsItChecked.bind(this);
    this.handleToggle = this.handleToggle.bind(this);
  }
  
  render() {
    return (
      <div>
        <Checkbox
          onChange={this.handleChange}
          inputRef={ref => this.myCheckbox = ref} />
        <Button type="button" onClick={this.handleToggle}>Toggle</Button>
        <Button type="button" onClick={this.handleIsItChecked}>Is it checked?</Button>
      </div>
    );
  }
  
  handleIsItChecked() {
    console.log(this.myCheckbox.checked ? 'Yes' : 'No');
  }
  
  handleToggle() {
    this.myCheckbox.checked = !this.myCheckbox.checked;
  }
}

ReactDOM.render(<App/>, document.querySelector('div'));
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react-bootstrap/0.30.8/react-bootstrap.min.js"></script>
<div></div>



回答2:

Have you tried setting an onChange property to your checkbox?

handleChange(event) {
    this.setState(*set checkbox state here*);
}

<Checkbox onChange={this.handleChange}></Checkbox>


回答3:

Thanks for the above answers. I generalized the above slightly for use when you have more than one checkbox in a given component:

  constructor() {
    super();
    this.state = { YourInputName: false };
    this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
  }

  render() {
    return (
      <div>
        <Checkbox
          name="YourInputName"
          onChange={this.handleCheckboxChange} />
      </div>
    );
  }

  handleCheckboxChange(event) {
    const target = event.target
    const checked = target.checked
    const name = target.name
    this.setState({
        [name]: checked,
    });
  }