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

使用TagCloud-reactJS构建移动端标签云出现重复问题求助

标签云重复显示问题排查与解决

我在个人作品集网站适配移动端标签云时,使用TagCloud-reactJS库,遇到标签云持续重复显示的问题,移动端效果如图:
移动端标签云重复显示截图

相关代码

index.js

import React, { useEffect, useState } from 'react'
import TagCloud from 'TagCloud';
import AnimatedLetters from '../AnimatedLetters';
import './index.scss'
import Loader from 'react-loaders';
import TagsCanvas from 'react-tags-canvas'

const container = '.tagCloud';
const texts = [
  'React.js', 'Python', 'JavaScript',
  'CSS3', 'Java', 'Jquery',
  'HTML5', 'C#', 'Ajax', 'ASP.NET',
  'SQL Server 2019', 'Visual Studio 2019',
  'Team Foundation Server (GIT)',
  'Google Maps API', 'SendGrid', 'Telerik UI', 'Blazor', 'Android Studio'
];

const options = {
  radius: 400,
  maxSpeed: 'fast',
  initSpeed: 'fast',
  direction: 135,
  keep: true
};

const Skills = () => {

   useEffect(() => {
     TagCloud(container, texts, options);
   })

   useEffect(() => {
     setTimeout(() => {
     return TagCloud(container, texts, options)
    }, 4000)
  }, [])

  
  const [letterClass, setLetterClass] = useState('text-animate')

  useEffect(() => {
     setTimeout(() => {
     return setLetterClass('text-animate-hover')
    }, 3000)
  }, [])

 
  return (
    <div  className='container skills-page'>
        <div className="text-zone">
          <h1>
            <AnimatedLetters
              letterClass={letterClass}
              strArray={['S', 'k', 'i', 'l', 'l', 's']}
              idx={15}
            />
          </h1>
          <p>
            Expert in a wide variety of coding languages such as HTML5, CSS3, Javascript, Jquery, React, Bootstrap, Git, Java, Python, C#, SQL, etc.
          </p>
          <p float="left">
             I specialize in building aesthetic looking websites on the front end, as well as making my back end code extremely efficient with the least amount of overhead possible. I try my best to ensure
             each page I build has a mobile friendly design and that my code is as easy to understand and as reusable as it can possibly be. 
          </p>
          <p>
            Feel free to visit my <a href='https://github.com/EricTilton'>Github</a> page for some of my work.
          </p>
          
        </div>
      
         <div  className='cloudContainer'> 
        <span id="root" className="tagCloud"/>
        </div> 

        <div className='black'> 
        </div> 

        <Loader type="ball-grid-pulse" />
    </div>
  )
}

export default Skills

index.scss

.container.skills-page {
  a {
    color: #00e1ff
  }

  body{
    margin-top: 3px;
    padding: 1px;
    box-sizing: border-box;
  }

  .text-zone{
    margin-bottom: 400px;
  }

  .tagcloud {
    position: absolute;
    top: 100px;
    right: auto;
    bottom: 6000px;
    color: #fff;
    font-family: 'Poppins', sans-serif;  
    font-size: 15px;
    font-weight: 650;
    margin-left: 50%;
    mask-repeat: no-repeat;
  }
  
  .tagcloud--item:hover {
    color: #00e1ff 
  }
}

@media screen and (max-width: 1200px)  {
  .cloudContainer{
    position: relative;
    transform: scale(0.5) translate(-100%, -100%);
    top: 800px;
    right: 25px;
  }

  .tagCloud {
    position: relative;
    top: auto;
    bottom: 500px;
    color: #fff;
    font-family: 'Poppins', sans-serif;  
    font-size: 15px;
    font-weight: 650;
    margin-right:  200%;
    mask-repeat: no-repeat;
    width: 100%;
    height: 100%;
    transform: scale(0.5) translate(-100%, -100%);
  }

  h1 {
    font-size: 53px;
    font-family: 'Coolvetica';
    color: #00e1ff;
    font-weight: 400;
    margin-top: 0;
    position: relative;
    margin-bottom: 40px;
    left: -10px;

    &:before {
      content: '&lt;h1&gt;';
      font-family: 'La Belle Aurore', cursive;
      color: #00e1ff;
      font-size: 18px;
      position: absolute;
      margin-top: -10px;
      left: -10px;
      opacity: 0.6;
      line-height: 18px;
    }

    &:after {
      content: '&lt;h1/&gt;';
      font-family: 'La Belle Aurore', cursive;
      color: #00e1ff;
      font-size: 18px;
      line-height: 18px;
      position: absolute;
      left: -30px;
      bottom: -20px;
      margin-left: 20px;
      opacity: 0.6;
    }
  }
}

问题根源与修复方案

问题根源

  1. 重复初始化TagCloud:第一个useEffect无依赖数组,组件每次渲染都会执行初始化;加上第二个4秒延迟的初始化,导致多次生成标签,造成重复显示。
  2. 容器选择器不唯一:使用类选择器.tagCloud,若页面存在多个匹配元素或组件重复渲染,会重复挂载标签。

修复步骤

  1. 合并初始化逻辑,确保仅执行一次
    删除原有两个重复的useEffect,替换为以下代码,确保组件挂载时仅初始化一次,且卸载时清理实例:
useEffect(() => {
  // 清除容器内已有内容,避免重复
  const cloudContainer = document.querySelector(container);
  if (cloudContainer) {
    cloudContainer.innerHTML = '';
  }
  // 初始化标签云
  const cloudInstance = TagCloud(container, texts, options);
  
  // 组件卸载时销毁实例
  return () => {
    cloudInstance.destroy?.();
  };
}, []);
  1. 确保容器唯一性
    修改容器的id为唯一值,同时更新选择器:
// 修改container选择器
const container = '#tag-cloud-container';

// 对应JSX部分
<span id="tag-cloud-container" className="tagCloud"/>
  1. 简化移动端样式
    当前移动端样式的transform和定位易导致视觉重复,调整为:
@media screen and (max-width: 1200px)  {
  .cloudContainer{
    position: relative;
    transform: scale(0.7);
    top: 200px;
    margin: 0 auto;
    width: 80%;
  }

  .tagCloud {
    position: relative;
    color: #fff;
    font-family: 'Poppins', sans-serif;  
    font-size: 12px;
    font-weight: 650;
    width: 100%;
    height: 400px;
    transform: none;
  }
}

额外建议

  • 检查Skills组件是否被多次渲染(如路由切换重复挂载),确保组件仅渲染一次。
  • 查阅TagCloud库文档,确认是否有官方React组件用法,减少直接操作DOM带来的兼容性问题。

内容的提问来源于stack exchange,提问作者Eric Tilton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:55:22