React Table仅首次选中行点Apply前变灰 后续行直接隐藏问题
问题描述
- 点击
Show列下方的开关控件时,首次操作(例如操作Potato Soup对应的开关)整行会显示灰色选中背景,点击Apply按钮后该行被隐藏,表现符合预期。 - 后续对
Pea Soup等其他行执行相同操作时,选中的行不会先显示灰色背景,点击Apply后会直接被隐藏。 - 期望行为:第二次及之后选中行时也能正常展示灰色选中态,点击
Apply后再执行隐藏逻辑。

问题复现代码
export default function MenuDisplay() { const { menuId } = useParams(); const { match } = JsonData; const [hideSelected, setHideSelected] = useState(false); const [selected, setSelected] = useState({}); const rowSelectHandler = (id) => (checked) => { setSelected((selected) => ({ ...selected, [id]: checked })); }; const toggleShow = () => setHideSelected((hide) => !hide); const matchData = ( match.find((el) => el._id_menu === menuId)?._ids ?? [] ).filter(({ _id }) => { if (hideSelected) { return !selected[_id]; } return true; }); const getRowProps = (row) => { return { style: { backgroundColor: selected[row.values.id] ? "lightgrey" : "white" } }; }; const data = [ { Header: "id", accessor: (row) => row._id }, { Header: "Name", accessor: (row) => ( <Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>{row.name}</Link> ) }, { Header: "Description", accessor: (row) => row.description }, { Header: "Dishes", accessor: (row) => row.dishes, id: "dishes", Cell: ({ value }) => value && Object.values(value[0]).join(", ") }, { Header: "Show", accessor: (row) => ( <Toggle value={selected[row._id]} onChange={rowSelectHandler(row._id)} /> ) } ]; const initialState = { sortBy: [ { desc: false, id: "id" }, { desc: false, id: "description" } ], hiddenColumns: ["dishes", "id"] }; return ( <div> <Button primary onClick={toggleShow}> {hideSelected ? "Cancel" : "Apply"} </Button> <Table data={matchData} columns={data} initialState={initialState} withCellBorder withRowBorder withSorting withPagination rowProps={getRowProps} /> </div> ); }
问题根因
问题出在选中行背景色的取值判断逻辑上:
getRowProps中通过selected[row.values.id]判断当前行是否选中,这里的row.values是react-table根据列配置生成的单元格值集合,取值完全依赖列id配置的稳定性。- 定义id列时,
accessor传入的是函数,但没有显式指定列的id属性。react-table对于使用函数作为accessor的列,要求必须手动配置id作为列的唯一标识,首次渲染时碰巧能正确生成id为id的列值,所以首次操作表现正常。 - 点击
Apply后表格数据被过滤,触发表格重渲染,此时未显式指定id的列无法稳定生成对应值,row.values.id返回undefined,导致selected[undefined]始终为假值,灰色背景的判断逻辑直接失效。
修复方案
做两处调整即可彻底解决问题:
- 给id列显式添加
id配置,保证列标识全局稳定 - (推荐)行属性判断时直接从行实例的
original字段取原始数据的id,不依赖列生成的values集合,从根源避免列配置变动带来的取值问题
修复后的核心代码如下:
const getRowProps = (row) => { return { style: { // 直接从原始行数据取_id,不依赖row.values的生成结果 backgroundColor: selected[row.original._id] ? "lightgrey" : "white" } }; }; const data = [ { Header: "id", accessor: (row) => row._id, id: "id" // 显式指定列id,保证列标识稳定 }, // 其余列配置保持不变 // ... ];
修复后,无论进行多少次选中、Apply隐藏操作,选中行的灰色高亮效果都能正常展示,点击Apply后才会执行隐藏逻辑,完全符合预期。
内容的提问来源于stack exchange,提问作者Zokulko
相关产品推荐
相关产品推荐

