值变更时选中文本失去焦点问题求助
解决时间组件更新导致复制时失去焦点的问题
问题根源是每秒调用setState触发组件重渲染,显示时间的DOM元素被重新生成,导致选中的文本焦点丢失。以下是两种可行的解决方案:
方案一:使用useRef直接更新DOM(推荐)
通过useRef获取显示时间的DOM元素,每秒直接修改元素的文本内容,完全避免组件重渲染,从根源解决焦点丢失问题。
import { useEffect, useRef } from 'react'; function TimeDisplay() { // 定义ref关联DOM元素 const currentEpochRef = useRef(null); const localTimeRef = useRef(null); const utcTimeRef = useRef(null); useEffect(() => { const interval = setInterval(() => { // 直接更新DOM文本,不触发组件重渲染 if (currentEpochRef.current) { currentEpochRef.current.textContent = Math.floor(Date.now() / 1000); } if (localTimeRef.current) { localTimeRef.current.textContent = new Date().toString(); } if (utcTimeRef.current) { utcTimeRef.current.textContent = new Date().toUTCString(); } }, 1000); // 组件卸载时清除定时器 return () => clearInterval(interval); }, []); return ( <div> <p ref={currentEpochRef}>{Math.floor(Date.now() / 1000)}</p> <p ref={localTimeRef}>{new Date().toString()}</p> <p ref={utcTimeRef}>{new Date().toUTCString()}</p> </div> ); }
方案二:检测选中状态,暂停更新
通过监听鼠标和键盘事件,判断用户是否处于文本选中状态,选中时暂停时间更新,取消选中后恢复。
import { useState, useEffect } from 'react'; function TimeDisplay() { const [currentEpoch, setCurrentEpoch] = useState(Math.floor(Date.now() / 1000)); const [localTime, setLocalTime] = useState(new Date().toString()); const [utcTime, setUtcTime] = useState(new Date().toUTCString()); const [isSelecting, setIsSelecting] = useState(false); useEffect(() => { // 监听选中状态 const handleMouseDown = () => setIsSelecting(true); const handleMouseUp = () => setIsSelecting(false); const handleKeyUp = (e) => { if (e.key === 'Escape') setIsSelecting(false); }; document.addEventListener('mousedown', handleMouseDown); document.addEventListener('mouseup', handleMouseUp); document.addEventListener('keyup', handleKeyUp); const interval = setInterval(() => { // 非选中状态下才更新时间 if (!isSelecting) { setCurrentEpoch(Math.floor(Date.now() / 1000)); setLocalTime(new Date().toString()); setUtcTime(new Date().toUTCString()); } }, 1000); // 清理事件监听和定时器 return () => { clearInterval(interval); document.removeEventListener('mousedown', handleMouseDown); document.removeEventListener('mouseup', handleMouseUp); document.removeEventListener('keyup', handleKeyUp); }; }, [isSelecting]); return ( <div> <p>{currentEpoch}</p> <p>{localTime}</p> <p>{utcTime}</p> </div> ); }
内容的提问来源于stack exchange,提问作者sarfrazanwar
相关产品推荐
相关产品推荐

