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

如何解决点击事件触发时React组件重复渲染问题?附代码求助

修复重复渲染及点击隐藏问题的方案

问题根源

  1. 直接操作DOM类名而非遵循React状态管理逻辑,违背React数据流原则,易引发渲染异常
  2. useEffect未清理事件监听,可能导致事件重复绑定
  3. 未缓存事件处理函数,每次渲染都会创建新函数实例,触发不必要的effect执行

优化后的代码

import { useState, useCallback, useEffect, useRef } from 'react';

const YourComponent = () => {
  // 用状态控制.inner的显示/隐藏
  const [isInnerVisible, setIsInnerVisible] = useState(true);
  const innerRef = useRef(null);

  // 用useCallback缓存toggle函数,确保引用稳定
  const toggleInner = useCallback(() => {
    setIsInnerVisible(prevState => !prevState);
  }, []);

  // 处理.inner空白区域点击
  const handleInnerClick = useCallback((e) => {
    if (e.target === innerRef.current) {
      toggleInner();
    }
  }, [toggleInner]);

  useEffect(() => {
    const exitElement = innerRef.current?.querySelector('.exit');
    if (exitElement) {
      exitElement.addEventListener('click', toggleInner);
      // 组件卸载时清理事件监听,避免内存泄漏
      return () => exitElement.removeEventListener('click', toggleInner);
    }
  }, [toggleInner]);

  return (
    isInnerVisible && (
      <div 
        className='inner' 
        ref={innerRef}
        onClick={handleInnerClick}
      >
        <div className='contentSign'>
          <div className='form'>
            <h2>Đăng nhập</h2>
            <span className='exit'>X</span>
          </div>
        </div>
      </div>
    )
  );
};

export default YourComponent;

关键优化说明

  • 状态驱动渲染:通过isInnerVisible状态控制组件显示,替代手动操作DOM类名,完全遵循React数据流,从根源避免渲染异常
  • 函数缓存:用useCallback缓存事件处理函数,确保函数引用稳定,避免不必要的组件重渲染和effect重复执行
  • 事件清理:在useEffect返回函数中移除事件监听,防止内存泄漏和重复绑定
  • 简化DOM引用:仅用一个ref获取根容器,通过它查询内部元素,减少冗余定义
  • 条件渲染:直接通过状态控制组件是否渲染,比添加/移除类名更符合React最佳实践

内容的提问来源于stack exchange,提问作者Nguyễn Anh Đức

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:57:23