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

使用useAnimatedScrollHandler与BottomSheetScrollView时触发ReanimatedError求助

解决react-native-reanimated useAnimatedScrollHandler与@gorhom/bottom-sheet BottomSheetScrollView协作的ReanimatedError

问题描述

使用react-native-reanimated的useAnimatedScrollHandler绑定@gorhom/bottom-sheet的BottomSheetScrollView的onScroll事件时,触发以下错误:

ReanimatedError: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable., js engine: reanimated

改用React Native原生Animated API时,同样触发该错误。

报错原因

BottomSheetScrollView的onScroll事件回调参数并非Reanimated期望的原生滚动事件对象,而是经过@gorhom/bottom-sheet封装后的自定义对象,原生事件嵌套在nativeEvent属性中。直接将useAnimatedScrollHandler返回的处理函数绑定到onScroll,Reanimated无法解析封装后的对象,进而抛出HostObject转换错误。

解决方案

方法一:使用@gorhom/bottom-sheet内置的滚动控制器(推荐)

@gorhom/bottom-sheet提供了useBottomSheetScrollableController钩子,专门用于获取内部滚动组件的状态(包括滚动偏移量),无需手动处理滚动事件:

import React, { memo } from "react";
import { Text, VStack } from "@gluestack-ui/themed";
import { BottomSheetScrollView, useBottomSheetScrollableController } from "@gorhom/bottom-sheet";
import { useSharedValue, useAnimatedReaction } from "react-native-reanimated";

interface IWheelPickerProps {
  data: { value: string; label: string }[];
  contentClassname?: string;
}

export const WheelPicker = memo(({ data, contentClassname }: IWheelPickerProps) => {
  const scrollY = useSharedValue(0);
  const scrollableController = useBottomSheetScrollableController();

  // 监听滚动偏移变化,同步更新scrollY
  useAnimatedReaction(
    () => scrollableController.scrollableContentOffset.value.y,
    (newY) => {
      scrollY.value = newY;
    }
  );

  return (
    <VStack className={`flex-1 items-center ${contentClassname}`}>
      <BottomSheetScrollView scrollableController={scrollableController}>
        {data.map((item) => (
          <VStack className="flex-1 items-start justify-center" key={item.value}>
            <Text bold className="self-center text-xl">{item.label}</Text>
          </VStack>
        ))}
      </BottomSheetScrollView>
    </VStack>
  );
});

方法二:手动提取原生滚动事件对象

如果不想使用内置控制器,可以在onScroll回调中手动提取嵌套的原生事件对象,再传递给Reanimated的滚动处理函数:

import React, { memo } from "react";
import { Text, VStack } from "@gluestack-ui/themed";
import { BottomSheetScrollView } from "@gorhom/bottom-sheet";
import { useSharedValue, useAnimatedScrollHandler } from "react-native-reanimated";

interface IWheelPickerProps {
  data: { value: string; label: string }[];
  contentClassname?: string;
}

export const WheelPicker = memo(({ data, contentClassname }: IWheelPickerProps) => {
  const scrollY = useSharedValue(0);

  const animatedScrollHandler = useAnimatedScrollHandler({
    onScroll: ({ contentOffset: { y } }) => {
      scrollY.value = y;
    },
  });

  // 包装回调,提取原生事件传递给Reanimated处理函数
  const handleScroll = (event: any) => {
    animatedScrollHandler(event.nativeEvent);
  };

  return (
    <VStack className={`flex-1 items-center ${contentClassname}`}>
      <BottomSheetScrollView onScroll={handleScroll}>
        {data.map((item) => (
          <VStack className="flex-1 items-start justify-center" key={item.value}>
            <Text bold className="self-center text-xl">{item.label}</Text>
          </VStack>
        ))}
      </BottomSheetScrollView>
    </VStack>
  );
});

内容的提问来源于stack exchange,提问作者Юрий Архипов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:44:57