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

React Native Context场景useEffect首次渲染不触发问题排查

问题根因

这个异常是React Navigation栈导航缓存机制和useEffect触发逻辑不匹配导致的,和Context本身的实现无关:

  • React Navigation的Stack导航默认会缓存栈中所有已加载过的页面实例,你从WalletScreen调用goBack返回GameScreen时,WalletScreen组件不会被卸载,只是被切到后台失去焦点。
  • 你写的回显useEffect依赖项只有[attachedGifts]:第一次打开WalletScreen时attachedGifts初始值是null,useEffect虽然会执行,但不满足attachedGifts !== null的判断条件,回显逻辑不会跑。
  • 你在WalletScreen选完礼物调用dispatch更新Context值后,立刻执行了navigation.goBack(),此时WalletScreen正被切到后台,React Navigation会默认抑制后台非活跃页面的非紧急effect执行,所以这次attachedGifts变化对应的useEffect没有触发。
  • 当你后续再次导航进入WalletScreen时,attachedGifts的值从上次更新后没有发生任何变化,依赖项未变更,useEffect自然不会重新执行。
  • 按下ctrl+s触发热更新时,React会强制重新挂载/重渲染所有已缓存的组件,相当于手动触发了WalletScreen的逻辑执行,所以回显会临时恢复正常。
  • 至于GameScreen能正常打印出attachedGifts的正确值,是因为更新Context时GameScreen一直处于前台活跃状态,不受后台更新抑制规则的影响。
解决方案

方案1:使用导航焦点钩子触发回显(推荐,最适配导航场景)

不要仅依赖Context值变化触发回显,改为每次页面进入前台获得焦点时检查并执行回显逻辑,用React Navigation官方提供的useFocusEffect替换普通useEffect即可:
首先引入依赖:

import { useFocusEffect } from '@react-navigation/native';
import { useCallback } from 'react';

替换原有回显逻辑:

useFocusEffect(
  useCallback(() => {
    if (attachedGifts !== null) {
      let selectedIndex = -1
      const filteredArray = data.map(val => {
        if (val.id === attachedGifts.id) {
          selectedIndex = walletData.indexOf(val);
          setSelectedGiftIndex(selectedIndex);
          return {
            ...val,
            isSelect: !val.isSelect,
          };
        }
        return { ...val, isSelect: false };
      });
      setData(filteredArray);
    }
  }, [attachedGifts, data, walletData])
);

这个钩子会在每次页面进入前台获得焦点时主动执行,完全匹配你“每次进入钱包页都要检查已选礼物做回显”的业务需求,不受页面缓存、后台更新抑制的影响。

方案2:调整导航和状态更新的时序(临时兼容方案)

如果不想替换原有useEffect,可以把页面返回的逻辑延后到Context更新完成、所有effect执行完毕后再触发,避免页面在状态更新过程中被切到后台:

const attachGiftsToContext = (obj) => {
  dispatch(SET_GIFTS(obj));
  showToast('Gifts attached successfully!');
  // 放到宏任务队列,等当前状态更新对应的渲染、effect执行完成后再返回
  setTimeout(() => {
    navigation?.goBack();
  }, 0);
}

这个方案稳定性较差,不同设备渲染性能不同可能出现偶发不生效的问题,仅作为临时兼容使用。

额外注意点

你代码中Context的自定义Hook是匿名默认导出,建议改成具名导出避免可能的循环引用、热更新识别异常问题;另外要确认SET_GIFTS action creator正确返回了带payload的action结构,不过从GameScreen能拿到正确值来看这部分目前没有问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:54:42