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

React子父组件重渲染问题:多ID复制后Tooltip无法恢复默认状态

问题原因

每个CopyID组件都独立维护自己的triggeredIndex状态,组件间状态完全隔离。点击第二个组件时,只会更新它自身的状态,第一个组件的状态仍停留在之前的索引值,因此Tooltip不会自动变回"Copy"。


解决方案

方案1:子组件自动重置Tooltip状态(无需修改父组件,保持独立复用)

给子组件添加定时器,复制成功后自动在指定时间内重置状态,让Tooltip恢复默认值。这种方式完全保留子组件的独立性,父组件无需任何改动。

修改后的子组件代码:

import { Tooltip } from 'antd';
import React, { useState, useEffect } from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';

export const CopyID = ({ copyText, rowIndex }) => {
  const [triggeredIndex, setTriggeredIndex] = useState(null);

  // 复制成功后自动重置状态
  useEffect(() => {
    if (triggeredIndex !== null) {
      const timer = setTimeout(() => setTriggeredIndex(null), 2000); // 2秒后恢复默认
      return () => clearTimeout(timer); // 组件卸载时清除定时器,避免内存泄漏
    }
  }, [triggeredIndex]);

  const orderIdCopy = (i) => {
    setTriggeredIndex(i);
  };

  return (
    <CopyToClipboard text={copyText || ' '} onCopy={() => orderIdCopy(rowIndex)}>
      <Tooltip
        overlayClassName='custom-tooltip-style'
        title={triggeredIndex === rowIndex ? 'Copied' : 'Copy'}
        color={triggeredIndex === rowIndex ? '#018c5c' : 'geekblue'}>
        <i
          key={rowIndex}
          className='bx bx-copy me-2 align-middle fs-6 '
          style={{ cursor: 'pointer' }}>
        </i>
      </Tooltip>
    </CopyToClipboard>
  );
};

方案2:父组件维护全局状态(实现严格同步,复制新ID立刻恢复旧的Tooltip)

如果需要点击新ID时,旧的Tooltip立刻变回"Copy",就需要把共享状态提到父组件,但这不会影响子组件的复用性——子组件只负责接收props渲染UI,逻辑和状态由父组件统一管理,反而让子组件更纯粹。

父组件代码修改:

import { useState } from 'react';
import { CopyID } from './CopyID';

const ParentComponent = () => {
  const [lastCopiedIndex, setLastCopiedIndex] = useState(null);
  
  // 父组件统一处理复制事件,更新全局状态
  const handleCopy = (index) => {
    setLastCopiedIndex(index);
  };

  return (
    <table>
      {list.map((item, i) => (
        <tr key={i}>
          <td>
            <CopyID 
              copyText={item?.orderId} 
              rowIndex={i}
              lastCopiedIndex={lastCopiedIndex}
              onCopy={() => handleCopy(i)}
            /> 
          </td>
        </tr>
      ))}
    </table>
  );
};

子组件代码修改:

import { Tooltip } from 'antd';
import React from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';

export const CopyID = ({ copyText, rowIndex, lastCopiedIndex, onCopy }) => {
  return (
    <CopyToClipboard text={copyText || ' '} onCopy={onCopy}>
      <Tooltip
        overlayClassName='custom-tooltip-style'
        title={lastCopiedIndex === rowIndex ? 'Copied' : 'Copy'}
        color={lastCopiedIndex === rowIndex ? '#018c5c' : 'geekblue'}>
        <i
          key={rowIndex}
          className='bx bx-copy me-2 align-middle fs-6 '
          style={{ cursor: 'pointer' }}>
        </i>
      </Tooltip>
    </CopyToClipboard>
  );
};

如果觉得父组件代码重复,还可以封装成自定义Hook进一步简化使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 22:50:23