我正在尝试用一次只能选择一行来实现反应表。我已经经历了很多在反应表中选择多行的示例,但在我的情况下,当用户单击单选按钮时,用户只能选择一行,但目前可以选择所有行。任何人都可以帮我解决这个问题吗?
5 回答
使用 react-table 7.5.0,我将 CodeSandbox与 react-table 放在一起,在功能上一次只能选择一行。
本质上,我替换了一个无条件渲染的复选框:
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
)
带有条件渲染的复选框:
Cell: ({ row }) => {
if (
rows.filter((row) => row.isSelected).length < 1 ||
row.isSelected
) {
return (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
);
} else {
return (
<div>
<IndeterminateCheckbox
checked={false}
readOnly
style={row.getToggleRowSelectedProps().style}
/>
</div>
);
}
}
我过滤了所有行对象以检查所选行,然后如果所选行数小于 1 或该行已被选中,则有条件地呈现一个正常运行的反应表复选框。
如果选中的行数至少为 1 并且未选中该行,我会呈现一个无法选中的只读复选框。
理想情况下,我希望使用 react-table 的内置selectedRowIds而不是过滤所有行对象,但我无法弄清楚如何以允许我引用它的方式实现 useTable(),因为它是派生的从中。
这是我派生出来 的 react-table 的行选择代码沙箱。这是他们文档中的相关页面。
稍后我会将代码移动到内置代码片段中。
我知道这是一个老问题,但也许有人会发现这个解决方案很有用。从版本 7 开始,react-table 提供了一个stateReducer
可用于跟踪和更改表状态的方法。(在 v7 之前它有reducerHandlers
,但我没有深入探讨)。您可以按如下方式修改状态:
useTable(
{
columns,
data,
stateReducer: (newState, action) => {
if (action.type === "toggleRowSelected") {
newState.selectedRowIds = {
[action.id]: true
}
}
return newState;
},
}
...
这是带有描述的更改的CodeSandbox
您还可以覆盖 Cell(...) 道具函数上的 onChange 方法。
https://react-table.tanstack.com/docs/api/useRowSelect#row-properties
getToggleRowSelectedProps: Function(props) => props Use this function to get the props needed for a select row checkbox. Props: onChange: Function() style.cursor: 'pointer' checked: Bool title: 'Toggle Row Selected'
等我有空的时候再给个沙盒。
这是一个旧的,但这是我的解决方案:
从表实例中获取toggleAllRowsSelected 。
const {
allColumns,
getTableBodyProps,
getTableProps,
headerGroups,
prepareRow,
rows,
state,
toggleAllRowsSelected,
} = useTable(
{
columns,
data,
},
useRowSelect
);
然后像下面的代码一样将onClick添加到您的tr组件中(在我的代码中,tr已用情感设置样式并命名为StyledTableRow)。这将首先将所有选定的行设置为 false,然后切换当前行的isSelected值,如果它最初是false,如果它是true ,那么它已经被设置为 false。
如果您不想允许单击选定的行来取消选择它(例如,对于单选按钮),只需使用isSelected === true来阻止此处的任何操作。
{rows.map((row, i) => {
prepareRow(row);
// const isRowSelected = isSelected(row.id);
const { isSelected, getRowProps, getToggleRowSelectedProps, toggleRowSelected } = row;
const {
onChange,
indeterminate,
...toggleRowSelectedProps
} = getToggleRowSelectedProps();
console.log(row);
return (
<StyledTableRow
hover
{...getRowProps()}
{...toggleRowSelectedProps}
selected={isSelected}
onClick={() => {
const current = isSelected;
toggleAllRowsSelected(false);
if (!current) {
toggleRowSelected();
}
}}
>
{row.cells.map((cell, key) => (
这是“无线电式”行为的简单反应实现,useReducer
用于演示如何使用表的状态管理。
const { useReducer } = React; // --> for inline use
// import React, { useReducer } from 'react'; // --> for real project
const reducer = (state, action) => {
return { checkedId: action.id }
}
const App = () => {
const [state, dispatch] = useReducer(reducer, {})
const CheckBox = ({id}) => (
<input
id={id}
onClick={() => dispatch({ id })}
checked={state.checkedId === id}
type="checkbox"
/>
)
return (
<table border="1">
<tr><td><CheckBox id="1" /></td><td>John</td></tr>
<tr><td><CheckBox id="2" /></td><td>Doe</td></tr>
</table>
)
};
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>