React按钮悬停切换图片报错:TypeError: btn.map is not a function
解决React组件悬停崩溃的问题:TypeError: btn.map is not a function
嘿,我一眼就找到了问题的根源!你遇到的崩溃是因为在鼠标移出事件里错误地把数组状态改成了单个对象,导致后续渲染时无法调用数组的map方法。
错误原因分析
你的初始状态btn是一个包含三个按钮对象的数组,但在mouseOutHandler函数里,你使用了btn.find()而不是btn.map():
find()方法只会返回匹配条件的第一个对象,而不是整个数组- 当你调用
setBtn(btn.find(...))时,组件状态就从数组变成了单个对象 - 下一次渲染时,你尝试对这个对象调用
map()方法,自然会抛出TypeError: btn.map is not a function
另外,你的mouseOverHandler也有小问题:当遍历数组时,没有返回未匹配的元素,会导致数组里出现undefined,后续也可能引发渲染错误。
修正步骤
- 修正
mouseOutHandler,用map()替代find(),确保始终返回完整的数组:
const mouseOutHandler = (id) => { setBtn( btn.map((item) => { if (item.id === id) { return { ...item, src: item.defaultSrc }; } // 必须返回未修改的元素,保持数组结构完整 return item; }) ); };
- 完善
mouseOverHandler,补上未匹配元素的返回语句:
const mouseOverHandler = (id) => { setBtn( btn.map((item) => { if (item.id === id) { return { ...item, src: item.hoverSrc }; } // 返回原元素,避免数组出现undefined return item; }) ); };
修正后的完整组件逻辑
这样修改后,你的状态始终保持数组结构,悬停和移出时只会更新对应按钮的src属性,不会破坏整个数组:
import { useState } from "react"; export default function App() { const [btn, setBtn] = useState([ { id: 1, src: "https://via.placeholder.com/100?text=Default1", hoverSrc: "https://via.placeholder.com/100?text=Hover1", defaultSrc: "https://via.placeholder.com/100?text=Default1" }, { id: 2, src: "https://via.placeholder.com/100?text=Default2", hoverSrc: "https://via.placeholder.com/100?text=Hover2", defaultSrc: "https://via.placeholder.com/100?text=Default2" }, { id: 3, src: "https://via.placeholder.com/100?text=Default3", hoverSrc: "https://via.placeholder.com/100?text=Hover3", defaultSrc: "https://via.placeholder.com/100?text=Default3" } ]); const mouseOverHandler = (id) => { setBtn( btn.map((item) => { if (item.id === id) { return { ...item, src: item.hoverSrc }; } return item; }) ); }; const mouseOutHandler = (id) => { setBtn( btn.map((item) => { if (item.id === id) { return { ...item, src: item.defaultSrc }; } return item; }) ); }; return ( <div className="App"> {btn.map((item) => ( <button key={item.id} onMouseOver={() => mouseOverHandler(item.id)} onMouseOut={() => mouseOutHandler(item.id)} style={{ border: "none", background: "transparent" }} > <img src={item.src} alt={`btn-${item.id}`} /> </button> ))} </div> ); }
这样修改后,你的按钮悬停切换图片的功能就能正常工作,不会再崩溃啦!
内容的提问来源于stack exchange,提问作者program_bumble_bee
相关产品推荐
相关产品推荐

