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

值变更时选中文本失去焦点问题求助

解决时间组件更新导致复制时失去焦点的问题

问题根源是每秒调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:01:26