У меня есть начало кликабельного компонента списка, который будет служить для выбора элемента select. Как вы можете видеть из ниже, onClick
ListItem
, я передаю состояние дочернего элемента (ListItem
в этом случае) родителям (SelectableList
и CustomSelect
). Это работает нормально. Однако то, что я также хотел бы сделать, это изменить состояние компонентов sibling (других ListItems), чтобы я мог переключать их выбранные состояния при нажатии одного из ListItems.
В настоящий момент я просто использую document.querySelectorAll('ul.cs-select li)
, чтобы захватить элементы и изменить класс на выбранный, если он не соответствует индексу нажатого ListItem
. Это работает - в некоторой степени. Однако после нескольких кликов состояние компонента не было обновлено React (только на стороне клиента JS), и все начинает разрушаться. То, что я хотел бы сделать, это изменить this.state.isSelected
элементов списка сестер и использовать это состояние для обновления компонента SelectableList. Может ли кто-нибудь предложить лучшую альтернативу тому, что я написал ниже?
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 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;