【发布时间】:2016-11-14 21:18:37
【问题描述】:
所以我写了这个带有复选框的表格行组件,作为其他表格组件使用的第一列。以下是组件的简化版本
表格行:
import React, { Component, PropTypes } from 'react'
import { Checkbox } from 'react-bootstrap'
export default class TableRow extends Component {
constructor(props) {
super(props)
this.handleClickCheckbox = this.handleClickCheckbox.bind(this)
}
handleClickCheckbox() {
this.props.onClickCheckbox(this.props.entity.id)
}
render() {
const { checked, children } = this.props
return (
<tr>
<Checkbox
checked={checked}
onChange={this.handleClickCheckbox}
> </Checkbox>
{children}
</tr>
}
}
TableRow.propTypes = {
entity: PropTypes.shape({
id: PropTypes.number
}),
checked: PropTypes.bool,
onClickCheckbox: PropTypes.func
}
表:
import React, { Component, PropTypes } from 'react'
import { Table } from 'react-bootstrap'
import TableRow from './TableRow'
class SampleTable extends Component {
constructor(props) {
super(props)
this.state = {
checkedEntitiesIds: []
}
this.handleChangeChecked = this.handleChangeChecked.bind(this)
}
handleChangeChecked(id) {
const { checkedEntitiesIds } = this.state
const indexOfEntity = checkedEntitiesIds.indexOf(id)
// uncheck it if it's already checked, vice versa
this.setState({
checkedEntitiesIds : indexOfEntity > -1 ?
checkedEntitiesIds.filter((id, index) => index != indexOfEntity) :
[...checkedEntitiesIds, id]
})
}
render() {
const { entities } = this.props // can come from either parent component or subcribe to redux state
return (
<Table>
<thead>
<tr>
<th>placeholder for checkbox column</th>
<th>dummy header 1</th>
<th>dummy header 2</th>
</tr>
</thead>
<tbody>
{entities.map(entity =>
<TableRow
key={entity.id}
entity={entity}
checked={this.state.checkedIds.indexOf(action.id) > -1}
onClickCheckbox={this.handleChangeChecked}
>
<td>dummy table cell 1</td>
<td>dummy table cell 2</td>
</TableRow>
)}
</tbody>
</Table>
)
}
}
我将复选框设置为受控输入,因为选中的道具的值可能来自数据库。每个表行都有一个实体道具,可以唯一标识该行。我在表格组件中维护checkedEntitiesIds 状态,而不是在TableRow 组件中维护checked 状态,因为我觉得它为我提供了最大的灵活性。
我的一位同事不喜欢他必须在每个表组件中维护checkedEntitiesIds 状态以及handleChangeChecked 函数这一事实。他提出将checkedEntitiesIds状态加入TableRow,将handleChangeChecked的函数体移到TableRow。它的工作方式是每次单击/更改复选框时,TableRow 中的checkedEntitiesIds 状态将首先更新,然后传递回父表,因此父组件的checkedEntitiesIds 状态也会更新。这样他就不需要一遍又一遍地编写检查/取消检查逻辑。
有几件事困扰着我做出这样的改变:
- 让 TableRow 知道 checkedEntitiesIds,这应该是 Table 的一个状态,太违反直觉了。
- 重复的事实来源。
- TableRow 将有一个状态。如果我在这里错了,请纠正我。我的理解是那些低阶的哑组件应该很少有自己的状态。
- 在某些扫描仪中,复选框单击事件可能不一定会立即导致状态更改。例如,单击复选框时首先提示确认模式,并且仅在选择“是”时才更新状态。在 TableRow 中使用状态并不能提供这种灵活性。
我几乎可以肯定他的提议有点反模式。我只是不确定我放置组件的方式是否有意义,以及我列出的这些点是否有效。我是否遗漏了任何重要的东西来说服他?有没有办法在可重用性方面改进我的代码。任何见解将不胜感激。
【问题讨论】:
标签: checkbox reactjs components