【问题标题】:Call React Native code when reanimated SharedValue changes复活的 SharedValue 更改时调用 React Native 代码
【发布时间】:2021-10-28 18:26:59
【问题描述】:

我有一个reanimated ReadOnly<SharedValue<boolean>> 是从另一个SharedValue 派生的:

  const solidHeader = useDerivedValue(() => {
    return top.value <= -(height / 2);
  });

solidHeader.value 发生变化时,我想调用一个 RN 函数(未恢复)。具体来说,我想更新我的react-navigation 的标题透明度:

// This doesn't get called when `solidHeader.value` is updated in reanimated's thread
useEffect(() => {
  navigation.setOptions({headerTransparent: !solidHeader.value});
}, [solidHeader.value]);

我尝试了以下“似乎”是正确的方法,但后来我得到了错误

Reanimated: Animated.call node args should be an array with elements of type AnimatedNode. One or more of them are not AnimatedNodes
    useCode(() => {
      return call([solidHeader], (solidHeader) => {
        console.warn(solidHeader);
        navigation.setOptions({
          headerTransparent: !solidHeader,
        });
      });
    }, [solidHeader]);

我正在实现的目标可能吗?

【问题讨论】:

    标签: react-native react-native-reanimated react-native-reanimated-v2


    【解决方案1】:

    编辑:查看接受的答案。

    所以这就是我最终做的 hack:我认为这是因为 Reanimated 故意避免通过 JS/Reanimated 线程进行通信,所以我必须在 JS 端“轮询”以“依赖” " 关于复活方面的变化:

      // top is a SharedValue
      const { top, height } = useHeaderMeasurements();
      const [headerTransparent, setHeaderTransparent] = useState(
        top.value >= -(height / 2)
      );
    
      useEffect(() => {
        // Poll 60FPS and update RN state
        const check = setInterval(() => {
          setHeaderTransparent(top.value >= -(height / 2));
        }, 1000 / 60);
        return () => clearInterval(check);
      }, [top]);
    
      useEffect(() => {
        navigation.setOptions({ headerTransparent });
      }, [navigation, headerTransparent]);
    

    对于上下文:

    • useHeaderMeasurements 来自 react-native-collapsible-tab-view,它在引擎盖下使用 Reanimated V2
    • navigation.setOptions 来自react-navigation,当我们在Screen 中时,这要求我们在RN 端强制设置headerTransparent

    【讨论】:

      【解决方案2】:

      我认为 useCode 是为 reanimated 1 而 useSharedValue 是 reanimated 2。 关注文档:Try useAnimatedReaction

      【讨论】:

      • 我尝试执行以下操作:useAnimatedReaction(() =&gt; top.value &gt;= -(height / 2), (result, previous) =&gt; { if (result !== previous) { navigation.setOptions({ headerTransparent: result }); console.log(result); } }, [navigation]); 它似乎崩溃了,除非我注释掉 navigation.setOptions。似乎无法在第二个 Worklet 的主体中运行任何 JS 代码?
      • 是的。你应该将你的 js 代码包装在 runOnJs() 中,遵循这个link
      • 完美,成功了。我会将您的答案标记为已完成(并使用解决方案编辑答案)。
      猜你喜欢
      • 2021-06-14
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-30
      • 2018-06-26
      相关资源
      最近更新 更多