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

React Native中Reanimated call()内函数未随Props更新问题排查

嘿,这个问题我熟,是典型的闭包陷阱导致的!让我给你拆解下原因和解决办法:

问题原因:闭包陷阱导致的旧props引用

你遇到的核心问题是JavaScript闭包特性在React动画钩子中的体现:

  • useCode的依赖数组是[],这意味着它只会在组件第一次渲染时执行一次,生成对应的动画逻辑块。
  • 你在block里调用的onEmojiPress和onEmojiLongPress,是组件初始渲染时创建的函数——这些函数会捕获当时的reactions props值。
  • 当后续父组件更新reactions时,虽然组件会重新渲染并生成新的回调函数(捕获最新reactions),但useCode因为依赖数组为空,不会重新执行,所以动画逻辑里还是引用着旧版本的函数,自然用的是旧的reactions值。
解决方案:让动画逻辑依赖最新的回调函数

我们需要从两个方面修改代码,确保回调始终引用最新props,同时让useCode感知到函数的更新:

1. 用useCallback和useMemo包裹依赖props的内容

首先,把reacted的计算改成useMemo缓存,确保它随依赖项更新;然后用useCallback包裹回调函数,让它们的引用随依赖的props/状态变化而更新:

// 用useMemo缓存reacted的计算结果,依赖变化时自动更新
const reacted = useMemo(() => {
  return reactions.find(
    (reaction) =>
      (reaction.user ? reaction.user.id === loggedInUsersId : false) &&
      reaction.emoji === emoji
  );
}, [reactions, loggedInUsersId, emoji]);

// 用useCallback包裹回调函数,确保依赖更新时函数引用更新
const onEmojiPress = useCallback(async () => {
  console.log('Emoji Pressed');
  console.log(reactions.length);
  if (reacted) {
    await giveUnReaction(itemId, emoji, reacted.id);
  } else {
    await giveReaction(itemId, emoji);
  }
}, [reacted, giveUnReaction, giveReaction, itemId, emoji]);

const onEmojiLongPress = useCallback(() => {
  console.log('Emoji long Pressed');
  Vibration.vibrate(1);
  navigate(assets.strings.dashboard.feeds.reactantsPopup.NAME, {
    reactions,
    emoji,
  });
}, [reactions, emoji, navigate]);

2. 更新useCode的依赖数组

把useCode的依赖数组加上我们刚才用useCallback包裹的两个函数,这样当函数引用更新时,useCode会重新执行,生成新的动画逻辑块,确保调用的是最新的回调:

useCode(
  () => block([
    cond(
      eq(longPressState, State.BEGAN),
      set(shouldScale, 1)
    ),
    cond(
      eq(longPressState, State.FAILED),
      call([], onEmojiPress)
    ),
    cond(
      or(
        eq(longPressState, State.CANCELLED),
        eq(longPressState, State.END),
      ),
      call([], onEmojiLongPress)
    ),
  ]),
  // 加上依赖,确保回调更新时重新生成动画逻辑
  [longPressState, shouldScale, onEmojiPress, onEmojiLongPress]
);
验证修改

修改后,当父组件更新reactions props时,reacted会重新计算,onEmojiPress和onEmojiLongPress会更新为引用最新reactions的版本,useCode也会随之更新动画逻辑,此时触发LongPress的状态回调时,就能拿到最新的reactions值了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:37:40