You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中能否在对象类型Prop中传递回调函数?求助报错解决

问题:在对象类型Prop中传递回调函数时触发TypeError错误

我自定义了一个DataTable组件,通过columns、data和actions三个Prop传参,其中actions是包含回调函数handler的对象数组。但点击操作按钮时,控制台抛出TypeError: element.handler is not a function错误。

原DataTable组件代码

const DataTable = ({ columns, data, actions }) => {
return <>
<TableContainer>
        <Table sx={{ minWidth: 650 }} aria-label="simple table">
          <TableHead>
            <TableRow>
                <TableCell>#</TableCell>
                {
                    columns.map((item) => {
                        return (<TableCell key={item.key}>{item.label}</TableCell>);
                    })
                }
                {
                  actions && <TableCell>Actions</TableCell>
                }
            </TableRow>
          </TableHead>
          <TableBody>
            {data.map((row, index) => (
              <TableRow
                key={row.id}
                sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
              >
                <TableCell>
                  {index + 1}
                </TableCell>
                {
                    columns.map(item => {
                        return (<TableCell key={item.key}>{row[item.key] ? row[item.key] : ''}</TableCell>);
                    })
                }
                <TableCell>
                    {
                      actions.map((element) => {
                        return (<React.Fragment key={element.label}><span onClick={(row) => {element.handler(row.id)}}>{element.icon}</span></React.Fragment>)
                      })
                    }
                  </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
        <Pagination count={1} />
      </TableContainer>
</>
}

export default DataTable;

原组件使用代码

const [data, setData] = useState([]);
const columns = [
  {
    key: "provider",
    label: "Provider",
  },
  {
    key: "phone_number",
    label: "Phone Number",
  },
  {
    key: "status",
    label: "Status",
  },
];

const actions = [
  {
    icon: <VisibilityIcon sx={{ color: '#1976d2', cursor: 'pointer' }} />,
    label: 'View',
    handler: ''
  },
  {
    icon: <DeleteIcon sx={{ color: '#1976d2', marginLeft: '4px', cursor: 'pointer' }} />,
    label: 'Delete',
    handler: deleteHandler
  }
];

// Fetching data from api

const deleteHandler = async (id) => {
  // Calling delete api
}

return <>
  <Card>
    <CardContent>
      <DataTable columns={columns} data={data} actions={actions} />
    </CardContent>
  </Card></>;

问题原因与解决方案

核心原因

actions数组中第一个元素的handler被赋值为空字符串'',这不是函数类型,点击时调用element.handler(row.id)自然会触发类型错误。此外还有两个细节问题:

  1. onClick回调错误地将事件对象命名为row,覆盖了外层的行数据变量
  2. 未对actions的存在性和handler的类型做前置校验

修复步骤

  • 修正无效handler值:将不需要执行逻辑的handler设为空函数() => {},禁止使用字符串或其他非函数类型
  • 添加类型校验:调用handler前先判断其是否为函数,避免非函数值触发报错
  • 修正事件参数命名:将onClick的参数改为e(或直接忽略),使用外层的row变量获取行ID

修改后的组件使用代码

const [data, setData] = useState([]);
const columns = [
  {
    key: "provider",
    label: "Provider",
  },
  {
    key: "phone_number",
    label: "Phone Number",
  },
  {
    key: "status",
    label: "Status",
  },
];

// 修正View操作的handler为无操作函数
const actions = [
  {
    icon: <VisibilityIcon sx={{ color: '#1976d2', cursor: 'pointer' }} />,
    label: 'View',
    handler: () => {}
  },
  {
    icon: <DeleteIcon sx={{ color: '#1976d2', marginLeft: '4px', cursor: 'pointer' }} />,
    label: 'Delete',
    handler: deleteHandler
  }
];

const deleteHandler = async (id) => {
  // 调用删除API的逻辑
}

return (
  <Card>
    <CardContent>
      <DataTable columns={columns} data={data} actions={actions} />
    </CardContent>
  </Card>
);

修改后的DataTable组件代码

const DataTable = ({ columns, data, actions }) => {
  return (
    <TableContainer>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell>#</TableCell>
            {columns.map((item) => (
              <TableCell key={item.key}>{item.label}</TableCell>
            ))}
            {actions && <TableCell>Actions</TableCell>}
          </TableRow>
        </TableHead>
        <TableBody>
          {data.map((row, index) => (
            <TableRow
              key={row.id}
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
            >
              <TableCell>{index + 1}</TableCell>
              {columns.map(item => (
                <TableCell key={item.key}>{row[item.key] || ''}</TableCell>
              ))}
              {actions && (
                <TableCell>
                  {actions.map((element) => (
                    <React.Fragment key={element.label}>
                      <span 
                        onClick={() => {
                          // 先校验handler类型,再执行
                          typeof element.handler === 'function' && element.handler(row.id)
                        }}
                      >
                        {element.icon}
                      </span>
                    </React.Fragment>
                  ))}
                </TableCell>
              )}
            </TableRow>
          ))}
        </TableBody>
      </Table>
      <Pagination count={1} />
    </TableContainer>
  )
}

export default DataTable;

内容的提问来源于stack exchange,提问作者Ninja Turtle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 14:30:48