React中map函数内onClick事件不触发且列表key属性警告问题
问题解答
1. () => 语法的作用
React 事件绑定属性需要接收函数引用作为值:
- 如果你直接写
onClick={seeSummary(book.id)},组件渲染时会立即执行seeSummary函数,函数内部调用setState触发组件重渲染,重渲染时又会再次执行seeSummary,形成死循环,最终触发"too many re-renders"报错。 - 加
() =>是创建了一个匿名函数包裹逻辑,只有点击事件触发时才会执行函数内部的seeSummary(book.id),渲染阶段不会主动执行,就避免了死循环。
2. 列表key警告的修复方案
控制台的警告是因为你两处map遍历返回组件时,没有给每个子项加唯一的key属性,React 做虚拟DOM diff时依赖该属性优化渲染性能,修改如下:
书籍列表部分修改:
{bookList.map(book => ( <Node key={book.id} book={book} onClick={() => seeSummary(book.id)} /> ))}
摘要列表部分修改:
{contents[viewingId]?.content?.map((summaryData => ( <Summary // 优先用summaryData的业务唯一字段当key,没有的话暂时用索引兜底 key={summaryData.id ?? summaryData.content} summaryData={summaryData} /> )))}
3. 点击无响应的排查修复
这是最常见的自定义组件事件透传遗漏问题:
你自定义的Node组件需要将收到的onClick属性绑定到内部可点击的DOM元素上,否则点击不会触发事件,示例如下:
// Node 组件内部正确写法 const Node = ({ book, onClick }) => { // 必须把传入的onClick绑定到DOM节点上 return <div className="book-title" onClick={onClick}>{book.name}</div> }
另外你fetchBookSummary的状态更新写法有隐患,建议改成函数式更新避免状态覆盖问题:
const fetchBookSummary = (id) => { fetch(`http://localhost:5000/book/${id}`) .then(res => res.json()) .then(res => { // 用函数式更新获取最新的prev状态,避免闭包陷阱 setContents(prev => ({...prev, [id]: res[0]})) }) }
内容的提问来源于stack exchange,提问作者ellen
相关产品推荐
相关产品推荐

