Tôi đã có khởi đầu của một thành phần danh sách có thể nhấp sẽ phục vụ để điều khiển phần tử chọn. Như bạn có thể thấy từ bên dưới, onClick
của số ListItem
, tôi chuyển trạng thái của phần tử con (ListItem
trong trường hợp này) đến cha mẹ (SelectableList
và thành phần CustomSelect
). Điều này làm việc tốt. Tuy nhiên, những gì tôi cũng muốn làm là thay đổi trạng thái của các thành phần anh chị em (các ListItems khác) để tôi có thể chuyển trạng thái đã chọn khi một trong các ListItems được nhấp.Làm cách nào để đặt trạng thái của các thành phần anh chị em dễ dàng trong React?
Hiện tại, tôi chỉ đơn giản là sử dụng document.querySelectorAll('ul.cs-select li)
để lấy các phần tử và thay đổi lớp để chọn khi không khớp với chỉ số của số nhấp chuột ListItem
. Điều này hoạt động - đến một mức độ nào đó. Tuy nhiên, sau một vài cú nhấp chuột, trạng thái của thành phần chưa được cập nhật bởi React (chỉ bởi JS phía máy khách), và mọi thứ bắt đầu bị phá vỡ. Những gì tôi muốn làm là thay đổi this.state.isSelected
của các mục danh sách anh chị em, và sử dụng trạng thái này để làm mới thành phần SelectableList. Bất cứ ai có thể cung cấp một lựa chọn tốt hơn cho những gì tôi đã viết dưới đây?
var React = require('react');
var SelectBox = require('./select-box');
var ListItem = React.createClass({
getInitialState: function() {
return {
isSelected: false
};
},
toggleSelected: function() {
if (this.state.isSelected == true) {
this.setState({
isSelected: false
})
} else {
this.setState({
isSelected: true
})
}
},
handleClick: function(listItem) {
this.toggleSelected();
this.props.onListItemChange(listItem.props.value);
var unboundForEach = Array.prototype.forEach,
forEach = Function.prototype.call.bind(unboundForEach);
forEach(document.querySelectorAll('ul.cs-select li'), function (el) {
// below is trying to
// make sure that when a user clicks on a list
// item in the SelectableList, then all the *other*
// list items get class="selected" removed.
// this works for the first time that you move through the
// list clicking the other items, but then, on the second
// pass through, starts to fail, requiring *two clicks* before the
// list item is selected again.
// maybe there's a better more "reactive" method of doing this?
if (el.dataset.index != listItem.props.index && el.classList.contains('selected')) {
el.classList.remove('selected');
}
});
},
render: function() {
return (
<li ref={"listSel"+this.props.key}
data-value={this.props.value}
data-index={this.props.index}
className={this.state.isSelected == true ? 'selected' : '' }
onClick={this.handleClick.bind(null, this)}>
{this.props.content}
</li>
);
}
});
var SelectableList = React.createClass({
render: function() {
var listItems = this.props.options.map(function(opt, index) {
return <ListItem key={index} index={index}
value={opt.value} content={opt.label}
onListItemChange={this.props.onListItemChange.bind(null, index)} />;
}, this);
return <ul className="cs-select">{ listItems }</ul>;
}
})
var CustomSelect = React.createClass({
getInitialState: function() {
return {
selectedOption: ''
}
},
handleListItemChange: function(listIndex, listItem) {
this.setState({
selectedOption: listItem.props.value
})
},
render: function() {
var options = [{value:"One", label: "One"},{value:"Two", label: "Two"},{value:"Three", label: "Three"}];
return (
<div className="group">
<div className="cs-select">
<SelectableList options={options}
onListItemChange={this.handleListItemChange} />
<SelectBox className="cs-select"
initialValue={this.state.selectedOption}
fieldName="custom-select" options={options}/>
</div>
</div>
)
}
})
module.exports = CustomSelect;
Cảm ơn Colin. Có vẻ như tôi có thể thực hiện công việc này. Chỉ cần một chút logic trong '' 'onChildToggle()' '' để làm cho nó độc quyền lựa chọn, chứ không phải là một lựa chọn đa lựa chọn. –
Và nếu đó là lựa chọn duy nhất, chỉ cần lưu trữ một giá trị duy nhất có nghĩa là phần tử đã chọn. Đây thường là chỉ mục của mục dữ liệu đã chọn hoặc id của nó. Sau đó bạn có thể thực hiện 'selected = {this.state.selected === index}' hoặc 'selected = {this.state.selected === dataItem.id}' – FakeRainBrigand