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
相关产品推荐
相关产品推荐

