React实现Tooltip遇Invalid hook call错误:问题排查与解决
解决React钩子调用无效错误 + 实现技能卡片Tooltip
钩子错误排查
你提供的SkillsInfoCard组件代码本身并没有使用任何React Hooks,但出现了钩子调用无效的错误,原因大概率是以下几种:
- React与React DOM版本不匹配:检查
package.json中react和react-dom的版本号,确保两者完全一致。如果版本不同,执行npm install react@latest react-dom@latest(或yarn add react@latest react-dom@latest)更新依赖,再重启项目。 - 项目存在多个React副本:在项目根目录执行
npm ls react(或yarn list react)查看依赖树,若发现多个React实例,可通过npm的overrides或yarn的resolutions字段强制统一版本。例如在package.json中添加:
之后重新安装依赖即可。"overrides": { "react": "^18.2.0", "react-dom": "^18.2.0" } - 父组件违反钩子规则:检查调用
SkillsInfoCard的父组件,确保所有Hooks(如useState、useEffect)都直接写在函数组件的顶层,没有放在循环、条件判断或嵌套函数内部。
实现纯CSS Tooltip
当前代码的data-tip属性没有对应的样式支持,添加以下CSS代码即可实现悬停显示技能名称的Tooltip:
/* SkillsInfoCard.css */ .skill-item-container { margin: 8px; } .skill-item-img { width: 60px; height: 60px; object-fit: contain; } /* Tooltip样式 */ .tooltip { position: relative; display: inline-block; cursor: pointer; } .tooltip::after { content: attr(data-tip); position: absolute; bottom: 125%; left: 50%; transform: translateX(-50%); background-color: #2d3748; color: #fff; padding: 4px 8px; border-radius: 4px; font-size: 14px; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; } .tooltip::before { content: ""; position: absolute; bottom: 115%; left: 50%; transform: translateX(-50%); border: 5px solid transparent; border-top-color: #2d3748; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; } .tooltip:hover::after, .tooltip:hover::before { opacity: 1; }
同时简化组件代码(移除重复的data-tip属性):
import React from 'react'; import './SkillsInfoCard.css'; const SkillsInfoCard = ({ heading, skills }) => { const renderSkillInfo = (item) => ( <div className='skill-item-container' key={item.skill}> <div className='tooltip' data-tip={item.skill}> <img src={item.slink} alt={item.skill} className='skill-item-img' /> </div> </div> ); const renderRows = () => { const rows = []; for (let i = 0; i < skills.length; i += 4) { const row = skills.slice(i, i + 4); rows.push( <div className='skill-row' key={`row_${i / 4}`}> {row.map(renderSkillInfo)} </div> ); } return rows; }; return ( <div className='skill-div'>{renderRows()}</div> ); }; export default SkillsInfoCard;
内容的提问来源于stack exchange,提问作者omkargaikwad
相关产品推荐
相关产品推荐

