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

在React中添加/移除类是否需要使用useState?

React中类名切换与动画触发的实践疑问解答

现有实现代码

场景1:Intersection Observer 视口动画触发

useEffect(() => {
    const titleElements = document.querySelectorAll('.title, .description, .text');
    const options = {
      root: null,
      rootMargin: '0px',
      threshold: .4
    }

    const callbacks = (entries: any) => {
      entries.forEach((e: any) => {
        if (e.isIntersecting && e.target.className === 'text') {
          e.target.classList.add('text-animation');
        } else if (e.isIntersecting && e.target.className !== 'text') {
          e.target.classList.add('title-animation');
        } else {
          e.target.classList.remove('title-animation');
          e.target.classList.remove('text-animation');
        }
      });
    }

    let observer = new IntersectionObserver(callbacks, options);

    titleElements.forEach((e) => {
      observer.observe(e);
    })
  }, [])

场景2:价格变化动态返回类名(通过key触发重渲染)

const handleUpdateEffect = (price: any, i: any) => {
    if (prevList.length === 1) {
      return ''
    } else if (price > prevList[i].current_price) {
      return 'current-price-up'
    } else if (price < prevList[i].current_price) {
      return 'current-price-down'
    } else {
      return 'current-price-keep'
    }
  }

疑问解答

1. 在React中,用useEffect渲染后直接操作DOM添加/移除类,属于不良实践吗?

不算绝对的不良实践,要分场景判断。React核心是状态驱动DOM更新,但像Intersection Observer这种和浏览器DOM交互强绑定的API,直接操作DOM类名是合理的——因为你监听的是浏览器层面的视口状态,不属于React组件内部状态范畴。

但要注意几个细节:

  • 确保只操作当前组件渲染的DOM元素,避免误选其他组件的元素;
  • 组件卸载时要清理Observer(比如在useEffect的return函数里调用observer.disconnect()),防止内存泄漏;
  • 不要用这种方式修改和React内部状态绑定的类名。

2. 是否需为所有类的切换都使用useState?会有性能问题吗?

完全不需要。只有当类名变化和组件内部状态/Props变化强相关时,才需要用useState。如果用useState管控所有类名切换,反而会增加不必要的组件重渲染次数,引发性能问题——比如Intersection Observer场景中,我们只需要修改DOM类名,不需要组件整体重渲染。

性能问题的核心是不必要的重渲染:如果类名切换不需要带动组件其他UI变化,就没必要用useState;反之,如果类名变化需要联动其他组件内容,用useState才是合理的。

3. 直接DOM操作类、函数返回类与useState的适用场景分别是什么?是否需始终用useState切换类以触发动画?

直接DOM操作类的适用场景:

  • 处理浏览器层面的交互状态:比如视口监听、滚动位置、鼠标位置这类和DOM直接绑定的状态;
  • 第三方库/API需要直接操作DOM:比如动画库、图表库的DOM交互;
  • 不需要组件重渲染的局部样式修改:比如仅给单个元素加动画类,不影响组件其他部分。

函数返回类名的适用场景:

  • 类名完全由Props/现有状态计算得出:比如根据价格涨跌返回不同类名、根据用户权限返回样式类;
  • 类名变化需要触发组件重渲染:比如通过修改key让组件重新渲染以重复触发动画,这种场景符合React范式。

useState切换类名的适用场景:

  • 类名变化由组件内部交互触发:比如点击按钮切换激活类、表单输入状态切换;
  • 类名变化需要和其他状态联动:比如打开弹窗时同步修改弹窗样式类和遮罩状态;
  • 需要在多个子元素复用类名状态:比如组件内多个元素需根据同一状态切换类名。

不需要始终用useState切换类触发动画:动画触发的核心是类名变化,不管是DOM直接修改、函数计算还是useState驱动,只要类名能正确切换,CSS动画就能触发。选择哪种方式取决于场景,在符合React范式的同时兼顾性能即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:22:47