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

依赖更新后useCallback钩子未触发,如何实现过渡结束后输入框聚焦?

问题原因

React的回调ref仅在组件挂载、卸载或ref属性本身的引用发生变化时才会触发。你用useCallback包裹了ref回调并依赖transitionEnded,虽然当transitionEnded从false变为true时,useCallback会返回一个新的函数引用,但此时TextInput已经完成挂载,React不会主动重新执行这个回调,导致你的聚焦逻辑无法触发。

解决方案

推荐使用**useRef存储DOM元素 + useEffect监听状态变化**的方式,这种方案更简洁直接,避免回调ref的触发时机限制。

代码实现

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

// ...其他业务代码

const [transitionEnded, setTransitionEnded] = useState(false);
const inputRef = useRef(null); // 用useRef直接存储输入框DOM元素

// 监听transitionEnded状态变化,触发聚焦逻辑
useEffect(() => {
  // 确保状态已切换且DOM元素存在
  if (transitionEnded && inputRef.current) {
    if (shouldDelayFocus) {
      setTimeout(() => {
        focusAndUpdateMultilineInputRange(inputRef.current);    
      }, CONST.ANIMATED_TRANSITION);
    } else {
      focusAndUpdateMultilineInputRange(inputRef.current);
    }
  }
}, [transitionEnded, shouldDelayFocus]);

// 组件渲染部分
<ScreenWrapper
  onEntryTransitionEnd={() => {
    console.log("transition ended");
    setTransitionEnded(true);
  }}
>
  <TextInput ref={inputRef} />
</ScreenWrapper>

方案说明

  1. 用useRef直接绑定到TextInput的ref属性,可随时获取输入框的DOM元素,不受组件生命周期或状态变化限制。
  2. 通过useEffect监听transitionEnded的变化,一旦状态变为true且DOM元素存在,立即执行聚焦逻辑。
  3. 将shouldDelayFocus加入useEffect的依赖数组,确保延迟逻辑的正确性。

备选方案(若坚持使用回调ref)

如果一定要保留回调ref的写法,可以通过额外状态存储DOM元素,再结合useEffect触发聚焦:

const [transitionEnded, setTransitionEnded] = useState(false);
const inputRef = useRef(null);
const [inputElement, setInputElement] = useState(null);

const inputRefCallback = useCallback((el) => {
  setInputElement(el);
  inputRef.current = el;
}, []);

useEffect(() => {
  if (transitionEnded && inputElement) {
    if (shouldDelayFocus) {
      setTimeout(() => {
        focusAndUpdateMultilineInputRange(inputElement);    
      }, CONST.ANIMATED_TRANSITION);
    } else {
      focusAndUpdateMultilineInputRange(inputElement);
    }
  }
}, [transitionEnded, inputElement, shouldDelayFocus]);

// 组件部分
<ScreenWrapper
  onEntryTransitionEnd={() => setTransitionEnded(true)}
>
  <TextInput ref={inputRefCallback} />
</ScreenWrapper>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:53:41