使用react-native-reanimated封装组件时Animated.View/ScrollView读取错误
问题原因及解决方法
出现TypeError: Cannot read property 'ScrollView' of undefined和TypeError: Cannot read property 'View' of undefined的核心原因是react-native-reanimated v3+版本的API变更——该版本不再将Animated.ScrollView、Animated.View等组件挂载在Animated导出对象下,需要单独导入或手动创建。
解决方式(二选一)
方式一:直接导入对应Animated组件
从react-native-reanimated中直接导入AnimatedScrollView和AnimatedView,替换原代码中的Animated.ScrollView写法:
修改导入部分:
import React, { useRef, useEffect } from 'react'; import {StyleSheet, Text, View, ScrollView, } from "react-native"; import { useSharedValue, useAnimatedScrollHandler, useAnimatedStyle, withTiming, Easing, AnimatedScrollView // 单独导入AnimatedScrollView } from 'react-native-reanimated';
然后在JSX中使用<AnimatedScrollView>替代<Animated.ScrollView>:
<AnimatedScrollView style={styles.scrollView} onScroll={scrollHandler} > {/* 内容 */} </AnimatedScrollView>
方式二:用createAnimatedComponent包装原生组件
如果需要自定义包装逻辑,或者习惯旧写法,可以使用createAnimatedComponent将原生组件转为Animated版本:
import React, { useRef, useEffect } from 'react'; import {StyleSheet, Text, View, ScrollView, } from "react-native"; import { useSharedValue, useAnimatedScrollHandler, useAnimatedStyle, withTiming, Easing, createAnimatedComponent // 导入createAnimatedComponent } from 'react-native-reanimated'; // 包装原生组件 const AnimatedScrollView = createAnimatedComponent(ScrollView); const AnimatedView = createAnimatedComponent(View);
之后同样使用<AnimatedScrollView>即可。
额外修复:代码中的小错误
你的onBeginDrag回调里有个语法错误:isScrolling.value = true.valueOf; 应该改为isScrolling.value = true;,true.valueOf是函数引用,不是布尔值,会导致逻辑判断异常。
修改后的完整代码
import React, { useRef, useEffect } from 'react'; import {StyleSheet, Text, View, ScrollView, } from "react-native"; import { useSharedValue, useAnimatedScrollHandler, useAnimatedStyle, withTiming, Easing, AnimatedScrollView } from 'react-native-reanimated'; export default function App() { const translateY = useSharedValue(0); const lastContentOffset = useSharedValue(0); const isScrolling = useSharedValue(false); const scrollHandler = useAnimatedScrollHandler({ onScroll: (event) => { if ( lastContentOffset.value > event.contentOffset.y && isScrolling.value ) { console.log("正在向上滚动"); } else if ( lastContentOffset.value < event.contentOffset.y && isScrolling.value ) { console.log("正在向下滚动"); } lastContentOffset.value = event.contentOffset.y; }, onBeginDrag: (e) => { isScrolling.value = true; // 修复此处错误 }, onEndDrag: (e) => { isScrolling.value = false; } }); return ( <View style={styles.container}> <AnimatedScrollView style={styles.scrollView} onScroll={scrollHandler} > <Text style={styles.text}> Lorem ipsum dolor sit amet consectetur, adipisicing elit. Voluptas like or deslike and comment me </Text> </AnimatedScrollView> <View style={styles.action}> <Text style={styles.actionItem}>Comment</Text> <Text style={styles.actionItem}>Like</Text> <Text style={styles.actionItem}>Dislike</Text> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center", }, scrollView: { marginHorizontal: 20, }, text: { fontSize: 30, }, action: { flexDirection: "row", borderWidth: 1, borderRadius: 25, padding: 15, position: "absolute", bottom: 5, backgroundColor: "#000", width: "50%", justifyContent: "space-around", }, actionItem: { color: "#fff", }, });
内容的提问来源于stack exchange,提问作者Jason0011
相关产品推荐
相关产品推荐

