React/React Native中useRef内布尔值始终为false问题求助
问题根源
useRef的初始化函数仅在组件首次渲染时执行一次,此时PanResponder.create内部的回调会捕获当时的isKeyboardShown初始值(false)。后续keyboardState更新导致isKeyboardShown变化时,useRef中存储的PanResponder实例不会重新创建,回调函数始终引用第一次渲染时的旧值,因此即使键盘弹出,判断条件里的isKeyboardShown仍为false。
修复方案
方案一:用Ref存储最新的isKeyboardShown值
将isKeyboardShown存入独立的ref,确保PanResponder回调能访问到最新状态:
const isKeyboardShown = keyboardState?.isKeyboardShown ?? false; const isKeyboardShownRef = useRef(isKeyboardShown); // 监听isKeyboardShown变化,同步更新ref useEffect(() => { isKeyboardShownRef.current = isKeyboardShown; }, [isKeyboardShown]); const keyboardDissmissPanResponder = useRef( PanResponder.create({ onMoveShouldSetPanResponderCapture: (_e, gestureState) => { const isHorizonSwipe = Math.abs(gestureState.dx) > Math.abs(gestureState.dy); // 访问ref的current获取最新状态 return isHorizonSwipe && isKeyboardShownRef.current; }, onPanResponderGrant: Keyboard.dismiss, }), ).current;
方案二:依赖isKeyboardShown重新创建PanResponder
使用useMemo替代useRef,让PanResponder在isKeyboardShown变化时重新创建,确保回调引用最新值:
const isKeyboardShown = keyboardState?.isKeyboardShown ?? false; const keyboardDissmissPanResponder = useMemo(() => { return PanResponder.create({ onMoveShouldSetPanResponderCapture: (_e, gestureState) => { const isHorizonSwipe = Math.abs(gestureState.dx) > Math.abs(gestureState.dy); return isHorizonSwipe && isKeyboardShown; }, onPanResponderGrant: Keyboard.dismiss, }); }, [isKeyboardShown]);
方案对比
- 方案一不会频繁创建PanResponder实例,性能更优,适合状态频繁变化的场景;
- 方案二代码更简洁,当
isKeyboardShown变化不频繁时可以优先使用。
内容的提问来源于stack exchange,提问作者sai
相关产品推荐
相关产品推荐

