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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:05:05