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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:34:55