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 />} </> ); }
报错根因
该问题的核心原因是缺少组件卸载时的异步定时器清理逻辑:
- 根据根路由的逻辑,用户登出时登录状态被置为false,
Login组件会从路由树中被完全卸载,绑定了inputRef的TextInput DOM实例会被销毁,inputRef.current会被自动重置为null - React
useEffect注册的setTimeout定时器属于独立的异步任务,不会因为组件被卸载自动终止 - 当1秒延迟到期后,依然处于挂起状态的定时器回调会尝试读取已经失效的
inputRef.current,对null值调用focus()方法,就会抛出空引用报错
首次进入页面没有报错,是因为从组件挂载到定时器触发的1秒周期内没有发生组件卸载,ref始终持有有效的DOM引用
修复方案
- 在
useEffect的清理回调中,手动清除组件卸载时仍处于挂起状态的定时器,避免异步回调在组件销毁后执行 - 在聚焦逻辑中增加非空判断做兜底,避免极端场景下的空引用异常
修改后的核心代码:
useEffect(() => { // 保存定时器实例 const focusTimer = setTimeout(() => { // 可选:非空判断兜底 inputRef.current?.focus(); }, 1000); // 组件卸载时执行清理操作 return () => { clearTimeout(focusTimer); }; }, []);
内容的提问来源于stack exchange,提问作者Satyam
相关产品推荐
相关产品推荐

