useCallback依赖数组不包含数据时为什么组件不更新?

开发者向景 阅读 28

我在做一个表格组件时遇到奇怪的问题,当用useCallback包裹行点击处理函数后,虽然数据更新了但组件没重新渲染。尝试过把setData放进依赖数组,但这样又会无限渲染。

代码大概是这样的:


const Table = ({ rows }) => {
  const [selectedId, setSelectedId] = useState(null);
  
  const handleRowClick = useCallback((id) => {
    setSelectedId(id);
  }, []); // 这里依赖数组空着
  
  return (
    <table>
      {rows.map(row => (
        <tr onClick={() => handleRowClick(row.id)}>
          <td>{row.name}</td>
        </tr>
      ))}
    </table>
  );
};

当父组件传入新的rows数据时,点击行后selectedId虽然变化了,但表格行样式没更新。控制台没有报错,这是useCallback的使用问题吗?

我来解答 赞 12 收藏
二维码
手机扫码查看
1 条解答
百里玉佩
问题应该出在 useCallback 的依赖数组为空,导致 handleRowClick 没有感知到 rows 的变化。虽然你的数据更新了,但因为依赖数组为空,handleRowClick 始终是之前的版本,行点击时传入的 row.id 可能还是旧的数据。

解决办法是把 rows 加入到依赖数组中,但直接加可能会引发无限渲染的问题,所以可以用一个技巧:不要直接依赖 rows,而是通过父组件传入的最新值来处理。

试试这样改:

const Table = ({ rows }) => {
const [selectedId, setSelectedId] = useState(null);

// 把 rows 加入依赖数组
const handleRowClick = useCallback((id) => {
setSelectedId(id);
}, [rows]); // 这里加入 rows

return (
<table>
{rows.map(row => (
<tr
key={row.id}
onClick={() => handleRowClick(row.id)}
style={{ backgroundColor: selectedId === row.id ? 'yellow' : 'white' }}
>
<td>{row.name}</td>
</tr>
))}
</table>
);
};


这里的关键是,useCallback 的依赖数组需要包含所有可能影响函数逻辑的变量。如果你担心性能问题,可以确保 rows 只有在必要时才更新,或者用 React.memo 包裹子组件来优化渲染。

最后,记得给每一行加上唯一的 key(比如 row.id),不然 React 可能会因为缺少标识而无法正确更新 DOM。
点赞 7
2026-02-02 18:30