首页 > 解决方案 > Reanimated 中的错误“试图从不同的线程同步调用函数 res”

问题描述

有一些手势处理程序可以在浏览器中正常工作,但我在 iOS 上的 useAnimatedGestureHandler 挂钩的 onEnd 回调中收到此错误。

这是与我要添加的手势相关的所有代码

    const headerHeight = useSharedValue(176)

    const outerStyle = useAnimatedStyle(() => ({
        minHeight: 176,
        maxHeight: 416,
        height: headerHeight.value,
        borderBottomLeftRadius: 20,
        borderBottomRightRadius: 20,
        position: 'relative',
        overflow: 'visible',
        zIndex: 502,
    }))

    const innerStyle = useAnimatedStyle(() => ({
        overflow: 'hidden',
        height: headerHeight.value,
        minHeight: 176,
        maxHeight: 416,
        borderBottomLeftRadius: 20,
        borderBottomRightRadius: 20,
    }))

    
    const resizeHeaderHeight = useAnimatedGestureHandler({
        onStart: () => {},
        onActive: (event) => {
            headerHeight.value = event.absoluteY
        },
        onEnd: () => {
            if(headerHeight.value < 305) {
                headerHeight.value  = withTiming(176, {
                    duration: 500,
                })
                setHeaderExpanded(false)
            } else {
                headerHeight.value  = withTiming(416, {
                    duration: 500,
                })
                setHeaderExpanded(true)
            }   
        },
    })

    return <>
    <PanGestureHandler onGestureEvent={resizeHeaderHeight}>
        <Animated.View style={outerStyle}>
            <Animated.View style={innerStyle}>
                <HeaderComponent
                    expandable={true}
                    hideContentCollapsed={false}
                    onClickExpand={() => {
                        // setHeaderExpanded(!headerExpanded)
                    }}
                    onClickTitle={openMonthPicker}
                >{{
                    title: <Title />,
                    content: <HeaderCalendar />,
                    buttons: [
                        <RefreshButton key='refresh' />,
                        <AssignmentOffersButton key='assignment-offers' navigation={navigation} />,
                        <FiltersButton key='filters' navigation={navigation} />,
                    ],
                }}</HeaderComponent>
                </Animated.View>
            <ExpandButton isExpanded={headerExpanded} onClick={()=> {}} />
            </Animated.View>
        </PanGestureHandler>

        {headerExpanded && <Overlay onClick={() => {
            setHeaderExpanded(!headerExpanded)
        }} />} 
    </>
}

export default observer(Header)

已尝试将 onEnd 定义为“worklet”并使用建议的 runOnJs 函数来解决此问题,但我不确定我是否正确执行此操作,因为每次 onEnd 运行时我仍然有错误。

标签: react-nativereact-native-reanimatedreact-native-gesture-handlerreact-native-reanimated-v2

解决方案


对于迟到的回复,我很抱歉。我认为,正如您已经提到的,问题在于不使用 runOnJS。基本上onStart、onActive 和onEnd 是成熟的worklet,即将在UI 线程上执行的javascript 函数。因此,如果您的函数只能在 javascript 线程上执行并且需要从工作集启动,则必须始终使用 runOnJS 指定。

更具体地说,在 onEnd 函数中,您应该像这样包装 setHeaderExpanded 函数: runOnJS(setHeaderExpanded)(true) // the boolean value you want to use.


推荐阅读