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

Input组件重挂载时不支持React useRef Hook导致登录页自动聚焦报错

登录组件自动聚焦逻辑重挂载后报错问题

触发场景

  • 首次打开登录页面时,组件挂载1秒后文本输入框自动聚焦的功能运行完全正常
  • 用户完成登出操作返回登录页面(登录组件重新挂载)后,等待1秒会触发控制台空引用类报错

相关代码实现

登录页核心逻辑

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

function Login(props) {
  // 省略业务逻辑代码
  const inputRef = useRef(null);

  // 实现挂载1秒后自动聚焦的逻辑
  useEffect(() => {
    setTimeout(() => {
      inputRef.current.focus();
    }, 1000);
  }, []);

  return(
    // 省略其他页面布局代码
    <TextInput
      ref={inputRef}
      label="Enter your name"
    />
  )
}

export default Login;

根路由认证切换逻辑

function RootNavigation(props) {
  const loginState = useSelector(state => state.LoginSlice.loginStatus);
  const otpLoginState = useSelector(state => state.OtpConfirmSlice.loginStatus);
  return (
    <>
      {loginState || otpLoginState ? <MyDrawer /> : <StartScreenNavigation />}
    </>
  );
}

报错根因

该问题的核心原因是缺少组件卸载时的异步定时器清理逻辑:

  1. 根据根路由的逻辑,用户登出时登录状态被置为false,Login组件会从路由树中被完全卸载,绑定了inputRef的TextInput DOM实例会被销毁,inputRef.current会被自动重置为null
  2. React useEffect注册的setTimeout定时器属于独立的异步任务,不会因为组件被卸载自动终止
  3. 当1秒延迟到期后,依然处于挂起状态的定时器回调会尝试读取已经失效的inputRef.current,对null值调用focus()方法,就会抛出空引用报错
    首次进入页面没有报错,是因为从组件挂载到定时器触发的1秒周期内没有发生组件卸载,ref始终持有有效的DOM引用

修复方案

  1. 在useEffect的清理回调中,手动清除组件卸载时仍处于挂起状态的定时器,避免异步回调在组件销毁后执行
  2. 在聚焦逻辑中增加非空判断做兜底,避免极端场景下的空引用异常

修改后的核心代码:

useEffect(() => {
  // 保存定时器实例
  const focusTimer = setTimeout(() => {
    // 可选:非空判断兜底
    inputRef.current?.focus();
  }, 1000);

  // 组件卸载时执行清理操作
  return () => {
    clearTimeout(focusTimer);
  };
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 19:36:03