React Table单元格添加单选按钮求助:选中状态异常与默认选中失效
解决React Table中行内单选按钮的两个问题
问题根源分析
- 行内单选按钮互斥:所有行的单选按钮共用了同一个
name="radio"属性,浏览器会将它们归为同一组,导致选中某一行的按钮时,其他行的同组按钮会自动取消选中。 - button1默认选中失效:当前用全局的
info.length判断按钮选中状态,而非针对当前行的id是否存在于info数组中,逻辑完全错误,导致默认状态下按钮选中表现异常。 - 事件处理逻辑错误:
handleRadioButton1Change直接清空整个info数组,不符合"仅移除当前行id"的需求;tableData中错误执行了事件处理函数而非传递引用。
修改后的完整代码
CustomRadioButtonComponent.tsx
import React from 'react'; import { Flex, RadioButton } from '你的UI库路径'; interface SomeProps { id: string | number; info: (string | number)[]; onBlur?: React.FocusEventHandler<HTMLInputElement>; onRadioButton1Change: (id: string | number) => void; onRadioButton2Change: (id: string | number, checked: boolean) => void; } const CustomRadioButtonComponent: React.FC<SomeProps> = ({ id, info, onBlur, onRadioButton1Change, onRadioButton2Change, }) => { // 判断当前行的选中状态:button1选中 = id不在info数组中 const isButton1Checked = !info.includes(id); // button2选中 = id在info数组中 const isButton2Checked = info.includes(id); const handleRadioButton1Change = React.useCallback(() => { onRadioButton1Change(id); }, [id, onRadioButton1Change]); const handleRadioButton2Change = React.useCallback((event: React.ChangeEvent<HTMLInputElement>) => { onRadioButton2Change(id, event.target.checked); }, [id, onRadioButton2Change]); return ( <Flex flex={1}> <RadioButton name={`radio-${id}`} {/* 每行使用独立的name,避免组内互斥 */} id={`btn1-${id}`} label="button1" onChange={handleRadioButton1Change} onBlur={onBlur} checked={isButton1Checked} /> <RadioButton name={`radio-${id}`} {/* 与同组button1使用相同的动态name */} id={`btn2-${id}`} label="button2" checked={isButton2Checked} onChange={handleRadioButton2Change} onBlur={onBlur} /> </Flex> ); }; export default CustomRadioButtonComponent;
main.tsx
import React from 'react'; import { Table, Column, ColumnWithId } from 'react-table'; import CustomRadioButtonComponent from './CustomRadioButtonComponent'; interface Data { id: string | number; // 其他数据字段 } interface MainStepProps { values: Record<string, any>; setFieldValue: (key: string, value: any) => void; data: Data[]; allInfoMap: Record<string | number, string | number>; // 其他props } const mainStep: React.FC<MainStepProps> = ({ values, setFieldValue, data, allInfoMap }) => { const INFO_KEY = 'info'; const info = values[INFO_KEY] || []; // 确保info是数组,避免undefined // 切换到button1时,移除当前行id const handleRadioButton1Change = React.useCallback((id: string | number) => { const actualId = allInfoMap[id] ?? id; setFieldValue(INFO_KEY, info.filter(item => item !== actualId)); }, [info, setFieldValue, allInfoMap]); // 切换到button2时,添加/移除当前行id(使用函数式更新避免闭包问题) const handleRadioButton2Change = React.useCallback((id: string | number, checked: boolean) => { const actualId = allInfoMap[id] ?? id; setFieldValue(INFO_KEY, prevInfo => { if (checked) { // 避免重复添加 if (!prevInfo.includes(actualId)) { return [...prevInfo, actualId]; } return prevInfo; } else { return prevInfo.filter(item => item !== actualId); } }); }, [setFieldValue, allInfoMap]); const columns: Column<Data>[] = [ { Header: 'Name', id: 'name', accessor: 'name', // 假设data中有name字段 } as ColumnWithId<Data>, { Header: 'Radio buttons', id: 'radioButtons', Cell: ({ row: { selectState, original } }) => { // 仅当行被选中时显示按钮 if (selectState === 1) { return ( <CustomRadioButtonComponent id={original.id} info={info} onRadioButton1Change={handleRadioButton1Change} onRadioButton2Change={handleRadioButton2Change} /> ); } return null; }, }, { Header: 'Version', accessor: 'version', // 假设data中有version字段 }, ]; // 无需在tableData中注入事件函数,直接在Cell中使用全局处理函数即可 const tableData = React.useMemo(() => data, [data]); return ( <Table<Data> data={tableData} columns={columns} /> ); }; export default mainStep;
关键修改点说明
- 独立单选按钮组:给每行的单选按钮设置动态
name={radio-${id}},确保每行的按钮组相互独立,不会跨行互斥。 - 正确的选中状态判断:基于当前行id是否存在于
info数组中判断按钮选中状态,默认情况下info为空,所有行的button1都会被选中。 - 修复事件逻辑:
handleRadioButton1Change改为仅移除当前行的id,而非清空整个数组。handleRadioButton2Change使用函数式更新setFieldValue(prevInfo => ...),避免闭包导致的旧数据问题。
- 简化tableData:无需在数据中注入事件函数,直接在Cell组件中引用全局处理函数即可,减少不必要的渲染依赖。
内容的提问来源于stack exchange,提问作者Harika
相关产品推荐
相关产品推荐

