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

使用setOptions更新Header选项失效:scrollY触发headerTintColor无变化

问题原因

Reanimated的SharedValue是UI线程管理的变量,不会触发React组件重渲染。你代码里的header.value虽然能正确输出true/false,但React感知不到它的变化,导致:

  • useMemo依赖header.value,但组件没重渲染,getHeaderTintColor不会重新计算
  • 依赖getHeaderTintColor的useEffect也不会执行,navigation.setOptions自然不会更新header颜色
解决方案

用Reanimated的useAnimatedReaction监听header.value的变化,再在JS线程更新导航配置,有两种实现方式:

方式1:结合React状态

import { useAnimatedReaction, runOnJS } from 'react-native-reanimated';
import { useState } from 'react';

// ...其他原有代码

const [headerTintColor, setHeaderTintColor] = useState('blue');

const onScroll = useAnimatedScrollHandler((event) => {
  scrollY.value = event.contentOffset.y;
  header.value = event.contentOffset.y > 0;
}, []);

// 监听sharedValue变化,触发React状态更新
useAnimatedReaction(
  () => header.value,
  (newVal) => {
    runOnJS(setHeaderTintColor)(newVal ? 'red' : 'blue');
  },
  []
);

useEffect(() => {
  navigation.setOptions({
    headerTintColor,
    headerRight: () => (
      <VenueButtons
        sharePress={handleSharePress}
        favouritePress={() => handleFavouritePress()}
        isFavourite={isFavourite}
      />
    ),
  });
}, [loading, navigation, isFavourite, handleFavouritePress, headerTintColor]);

方式2:直接更新导航配置

import { useAnimatedReaction, runOnJS } from 'react-native-reanimated';

// ...其他原有代码

const header = useSharedValue(false);

const onScroll = useAnimatedScrollHandler((event) => {
  scrollY.value = event.contentOffset.y;
  header.value = event.contentOffset.y > 0;
}, []);

useAnimatedReaction(
  () => header.value,
  (newVal) => {
    // 直接在JS线程调用navigation.setOptions
    runOnJS(navigation.setOptions)({
      headerTintColor: newVal ? 'red' : 'blue',
      headerRight: () => (
        <VenueButtons
          sharePress={handleSharePress}
          favouritePress={() => handleFavouritePress()}
          isFavourite={isFavourite}
        />
      ),
    });
  },
  [loading, isFavourite, handleFavouritePress] // 要把所有依赖项加进来
);
核心要点
  • useAnimatedReaction专门用来监听SharedValue的变化,能在UI线程捕获到更新后,切换到JS线程执行回调
  • runOnJS必须用来包装JS线程的函数(比如setState、navigation.setOptions),因为UI线程不能直接执行这些函数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:34:56