Phản ứng lại JSX: chọn lựa chọn giữa các vùng được chọn trên tùy chọn <select>


402

Trong thành phần React cho <select>menu, tôi cần đặt selectedthuộc tính trên tùy chọn phản ánh trạng thái ứng dụng.

Trong render(), optionStateđược truyền từ chủ sở hữu trạng thái đến thành phần SortMothy. Các giá trị tùy chọn được truyền vào như propstừ JSON.

render: function() {
  var options = [],
      optionState = this.props.optionState;

  this.props.options.forEach(function(option) {
    var selected = (optionState === option.value) ? ' selected' : '';

    options.push(
      <option value={option.value}{selected}>{option.label}</option>
    );
  });

// pass {options} to the select menu jsx

Tuy nhiên, điều đó gây ra lỗi cú pháp khi biên dịch JSX.

Làm điều này sẽ thoát khỏi lỗi cú pháp nhưng rõ ràng không giải quyết được vấn đề:

var selected = (optionState === option.value) ? 'selected' : 'false';

<option value={option.value} selected={selected}>{option.label}</option>

Tôi cũng đã thử điều này:

var selected = (optionState === option.value) ? true : false;

<option value={option.value} {selected ? 'selected' : ''}>{option.label}</option>

Có một cách đề nghị để giải quyết điều này?


Nâng cao câu hỏi chỉ dành cho tiêu đề
ericgio

Câu trả lời:


648

React tự động hiểu booleans cho mục đích này, vì vậy bạn chỉ cần viết (lưu ý: không được đề xuất)

<option value={option.value} selected={optionsState == option.value}>{option.label}</option>

và nó sẽ xuất ra 'được chọn' một cách thích hợp.

Tuy nhiên, React làm cho điều này thậm chí còn dễ dàng hơn cho bạn. Thay vì xác định selectedtrên mỗi tùy chọn, bạn có thể (và nên) chỉ cần viết value={optionsState}vào chính thẻ chọn :

<select value={optionsState}>
  <option value="A">Apple</option>
  <option value="B">Banana</option>
  <option value="C">Cranberry</option>
</select>

Để biết thêm thông tin, hãy xem tài liệu thẻ React select .


56
Với phiên bản hiện tại của React (0.9), cài đặt thuộc tính được chọn trên các tùy chọn hoàn toàn không hoạt động. Đặt thuộc tính giá trị trên phần tử chọn thay thế.
liammclennan

2
tôi tải dữ liệu với ajax.defaultValue không hoạt động với tôi. Giá trị đang hoạt động nhưng tôi không thể chọn một mục khác trong danh sách chọn. Đang mở nhưng khi tôi chọn một trong số đó, nó sẽ chọn mục giá trị. Ý tưởng nào không?
dùng1924375

5
@ user1924375 bạn nên sử dụng sự kiện onChange onChange={this.handleSelect}và đặt giá trị trạng thái cho thành phần của mình, ví dụ: 'handleSelect: function () {this.setState ({value: event.target.value});} `Điều này sẽ đăng ký lại thành phần đã chọn của bạn với mới chọn mục. Hy vọng nó sẽ giúp bạn.
funnydaredevil

1
Mặc dù nó chưa được ghi lại, nhưng chỗ valuedựa trên <select>có thể là một mảng nếu bạn đã multiselectbật.
tirdadc

4
Thay vì sử dụng defaultValueđể khởi tạo
dewwwald

70

Bạn có thể làm những gì React cảnh báo bạn khi bạn cố gắng đặt thuộc tính "đã chọn" của <option>:

Sử dụng defaultValuehoặc valueđạo cụ trên <select>thay vì cài đặt selectedtrên <option>.

Vì vậy, bạn có thể sử dụng options.valuetrên defaultValuelựa chọn của bạn


9
Nếu tôi vẫn muốn chỉ ra tùy chọn hiện đang được chọn, tôi sẽ làm thế nào? Cách duy nhất hiện tại tôi có thể thực sự giữ tùy chọn được chọn (và giữ trạng thái của biểu mẫu để gửi bài trong tương lai) là bằng cách chọn select = true. Tôi đã thử đặt defaultValue và giá trị đạo cụ của phần tử select, nhưng điều này không hiển thị trong chế độ xem bằng cách đặt tùy chọn chính xác để chọn trong menu tùy chọn. Có lời khuyên nào không?
Các ống

4
Ví dụ có lẽ ??
shinzou

1
Không hoạt động đối với tôi: <select className = "form-control" value = "Mois">
Kuartz

2
defaultValue không hoạt động với phiên bản mới nhất
Hos Mercury

18

Đây là một giải pháp hoàn chỉnh kết hợp câu trả lời tốt nhất và các bình luận bên dưới nó (có thể giúp ai đó đấu tranh để ghép tất cả lại với nhau):

CẬP NHẬT CHO ES6 (2019) - sử dụng các hàm mũi tên và phá hủy đối tượng

trong thành phần chính:

class ReactMain extends React.Component {

  constructor(props) {
    super(props);
    this.state = { fruit: props.item.fruit };
  }

  handleChange = (event) => {
    this.setState({ [event.target.name]: event.target.value });
  }

  saveItem = () => {
    const item = {};
    item.fruit = this.state.fruit;
    // do more with item object as required (e.g. save to database)
  }

  render() {
    return (
      <ReactExample name="fruit" value={this.state.fruit} handleChange={this.handleChange} />
    )
  }

}

bao gồm thành phần (hiện là chức năng không trạng thái):

export const ReactExample = ({ name, value, handleChange }) => (
  <select name={name} value={value} onChange={handleChange}>
    <option value="A">Apple</option>
    <option value="B">Banana</option>
    <option value="C">Cranberry</option>
  </select>
)

TRẢ LỜI TRƯỚC (sử dụng liên kết):

trong thành phần chính:

class ReactMain extends React.Component {

  constructor(props) {
    super(props);
    // bind once here, better than multiple times in render
    this.handleChange = this.handleChange.bind(this);
    this.state = { fruit: props.item.fruit };
  }

  handleChange(event) {
    this.setState({ [event.target.name]: event.target.value });
  }

  saveItem() {
    const item = {};
    item.fruit = this.state.fruit;
    // do more with item object as required (e.g. save to database)
  }

  render() {
    return (
      <ReactExample name="fruit" value={this.state.fruit} handleChange={this.handleChange} />
    )
  }

}

bao gồm thành phần (hiện là chức năng không trạng thái):

export const ReactExample = (props) => (
  <select name={props.name} value={props.value} onChange={props.handleChange}>
    <option value="A">Apple</option>
    <option value="B">Banana</option>
    <option value="C">Cranberry</option>
  </select>
)

thành phần chính duy trì giá trị được chọn cho trái cây (ở trạng thái), thành phần đi kèm hiển thị phần tử được chọn và các bản cập nhật được chuyển trở lại thành phần chính để cập nhật trạng thái của nó (sau đó lặp lại thành phần được bao gồm để thay đổi giá trị đã chọn).

Lưu ý việc sử dụng tên prop cho phép bạn khai báo một phương thức handleChange duy nhất cho các trường khác trên cùng một hình thức bất kể loại của chúng.


Lưu ý dòng trong hàm tạo this.handleChange.bind(this);nên this.handleChange = this.handleChange.bind(this);
Sẽ cạo râu

đối với những người như tôi, những người tự hỏi họ ... nghĩa là gì: Reacjs.org/docs/jsx-in-depth.html#s lây
phân phối

@talsibony - đó thực sự là toán tử lây lan, nhưng trong mã mẫu của tôi, nó chỉ có nghĩa là chèn một số mã khác vào đây !
Andy Lorenz

@AndyLorenz Vì vậy, trong trường hợp đó, tôi khuyên bạn nên xóa nó ... :) hoặc chỉ viết bình luận như // phần còn lại của mã của bạn
talsibony

8

Dưới đây là ví dụ mới nhất về cách làm điều đó. Từ các tài liệu phản ứng , cộng với cú pháp phương thức "mũi tên béo" tự động ràng buộc.

class FlavorForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};
  }

  handleChange = (event) =>
    this.setState({value: event.target.value});

  handleSubmit = (event) => {
    alert('Your favorite flavor is: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Pick your favorite flavor:
          <select value={this.state.value} onChange={this.handleChange}>
            <option value="grapefruit">Grapefruit</option>
            <option value="lime">Lime</option>
            <option value="coconut">Coconut</option>
            <option value="mango">Mango</option>
          </select>
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
} 

4

Chỉ cần thêm tùy chọn đầu tiên của thẻ chọn của bạn:

<option disabled hidden value=''></option>

Điều này sẽ trở thành mặc định và khi bạn chọn một tùy chọn hợp lệ sẽ được giải quyết theo trạng thái của bạn


1
***Html:***
<div id="divContainer"></div>

var colors = [{ Name: 'Red' }, { Name: 'Green' }, { Name: 'Blue' }];
var selectedColor = 'Green';

ReactDOM.render(<Container></Container>, document.getElementById("divContainer"));

var Container = React.createClass({
    render: function () {
        return (
        <div>            
            <DropDown data={colors} Selected={selectedColor}></DropDown>
        </div>);
    }
});

***Option 1:***
var DropDown = React.createClass(
{
    render: function () {
        var items = this.props.data;
        return (
        <select value={this.props.Selected}>
            {
                items.map(function (item) {
                    return <option value={item.Name }>{item.Name}</option>;
                })
            }
        </select>);
    }
});

***Option 2:***
var DropDown = React.createClass(
{
    render: function () {
        var items = this.props.data;
        return (
        <select>
            {
                items.map(function (item) {
                    return <option value={item.Name} selected={selectedItem == item.Name}>{item.Name}</option>;
                })
            }
        </select>);
    }
});

***Option 3:***
var DropDown = React.createClass(
    {
        render: function () {
            var items = this.props.data;
            return (
            <select>
                {
                    items.map(function (item) {

                                            if (selectedItem == item.Name)
                    return <option value={item.Name } selected>{item.Name}</option>;
                else
                    return <option value={item.Name }>{item.Name}</option>;
                    })
                }
            </select>);
        }
    });

1
Mặc dù không có lời giải thích nào được đưa ra, người ta không thực sự cần thiết. Nhiều cách để tiếp cận cùng một vấn đề thực sự là cái nhìn sâu sắc hữu ích. Cảm ơn
DJ2

0

Tôi đã gặp sự cố với <select>các thẻ không cập nhật thành chính xác <option>khi trạng thái thay đổi. Vấn đề của tôi dường như là nếu bạn kết xuất hai lần liên tiếp, lần đầu tiên không được chọn trước <option>nhưng lần thứ hai với một lần, thì <select>thẻ không cập nhật trên kết xuất thứ hai, nhưng vẫn ở mặc định trước.

Tôi tìm thấy một giải pháp cho việc này bằng cách sử dụng refs . Bạn cần có một tham chiếu đến <select>nút thẻ của mình (có thể được lồng trong một số thành phần), sau đó cập nhật thủ công thuộc valuetính trên nó, trong componentDidUpdatehook.

componentDidUpdate(){
  let selectNode = React.findDOMNode(this.refs.selectingComponent.refs.selectTag);
  selectNode.value = this.state.someValue;
}

0

Đăng một câu trả lời tương tự cho MULTISELECT / optgroups:

render() {
  return(
    <div>
      <select defaultValue="1" onChange={(e) => this.props.changeHandler(e.target.value) }>
        <option disabled="disabled" value="1" hidden="hidden">-- Select --</option>
        <optgroup label="Group 1">
          {options1}
        </optgroup>
        <optgroup label="Group 2">
          {options2}
        </optgroup>
      </select>
    </div>
  )
}

0

Tôi có một giải pháp đơn giản là theo HTML cơ bản.

<input
  type="select"
  defaultValue=""
  >
  <option value="" disabled className="text-hide">Please select</option>
  <option>value1</option>
  <option>value1</option>
</input>

.text-hide là một lớp của bootstrap, nếu bạn không sử dụng bootstrap, thì đây là:

.text-hide {
  font: 0/0 a;
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}

-1

Tôi đã khắc phục một vấn đề tương tự bằng cách đặt defaultProps:

ComponentName.defaultProps = {
  propName: ''
}

<select value="this.props.propName" ...

Vì vậy, bây giờ tôi tránh các lỗi khi biên dịch nếu prop của tôi không tồn tại cho đến khi gắn kết.


Điều đó thực sự không giải quyết được vấn đề. Bạn sẽ nhận được điều này: Cảnh báo: Loại prop không thành công: Bạn đã cung cấp valueprop cho trường biểu mẫu mà không cần onChangexử lý. Điều này sẽ khiến một trường chỉ đọc. Nếu các lĩnh vực nên được sử dụng đột biến defaultValue. Nếu không, đặt một trong hai onChangehoặc readOnly.
Jason Rice
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.