React/React Native中离开页面时如何移除Ref解决键盘闪烁问题
解决方案:清理Ref与修复Mobile Safari焦点问题
一、修复页面返回时的键盘闪烁问题
问题根源是页面离开时未清理输入框的ref引用,导致返回时旧的ref仍持有已卸载的组件实例,引发不必要的焦点操作。需要在页面失焦时完成两项关键清理:
修改useFocusEffect逻辑
注意清理函数要放在useCallback顶层返回(原代码中清理函数嵌套在setTimeout内部,无法被正确执行):
useFocusEffect( useCallback(() => { focusTimeoutRef.current = setTimeout(() => { if (privateNotesInput.current) { privateNotesInput.current.focus(); } }, CONST.ANIMATED_TRANSITION); // 页面失焦时执行清理操作 return () => { // 清空定时器 if (focusTimeoutRef.current) { clearTimeout(focusTimeoutRef.current); focusTimeoutRef.current = null; } // 取消输入框焦点并清空ref引用 if (privateNotesInput.current) { privateNotesInput.current.blur(); privateNotesInput.current = null; } }; }, []), );
同步更新Ref回调逻辑
在InputWrapper的ref回调中,组件卸载时(el为null)要主动清空ref:
ref={(el: AnimatedTextInputRef) => { if (!el) { privateNotesInput.current = null; // 组件卸载时清空ref return; } privateNotesInput.current = el; updateMultilineInputRange(privateNotesInput.current); }}
二、修复Mobile Safari自动获焦问题
原逻辑仅依赖shouldAutoFocus判断不够严谨,需额外检查输入框当前是否处于聚焦状态,确保只有聚焦时才更新selection:
修改updateMultilineInputRange函数
const updateMultilineInputRange: UpdateMultilineInputRange = (input, shouldAutoFocus = true) => { if (!input) { return; } if ('value' in input && input.value && input.setSelectionRange) { const length = input.value.length; // 新增:检查输入框当前是否为活跃焦点 const isFocused = document.activeElement === input; // 仅在非Mobile Safari,或Mobile Safari下输入框已聚焦/允许自动聚焦时更新selection const shouldSetSelection = !(Browser.isMobileSafari() && !shouldAutoFocus && !isFocused); if (shouldSetSelection) { input.setSelectionRange(length, length); } input.scrollTop = input.scrollHeight; } };
额外注意事项
- 若
AnimatedTextInputRef没有blur方法,需替换为对应平台的失焦API(如React Native内置的blur()); - 后续若
useFocusEffect依赖其他变量(如privateNote),需将其加入依赖数组,避免闭包导致的逻辑异常。
内容的提问来源于stack exchange,提问作者sai
相关产品推荐
相关产品推荐

