expo 51.0.7 CRASH [TypeError: animatedRef.getTag is not a function (it is undefined)]
Description
My app crashes since i updated to expo@v51
my package.json: https://pastebin.com/WLbC7D4Y
With expo 49.0.13 it was working perfectly!!
const scrollRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useScrollViewOffset(scrollRef);
const [scrollX, setScrollX] = useState(new REACT_NATIVE_ANIMATED.Value(0));
<ScrollView ref={scrollRef} showsVerticalScrollIndicator={false} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} >
<Animated.View
style={[styles.image, imageAnimatedStyle]}
/>
</ScrollView>
Now i get this error with expo 51.0.7:
[TypeError: animatedRef.getTag is not a function (it is undefined)] in CompanyDetailScreen (created by SceneView) in StaticContainer in EnsureSingleNavigator (created by SceneView) in SceneView (created by CardContainer) in RCTView (created by CssInterop.View)
Steps to reproduce
- update expo to v51
- add "react-native-reanimated": "~3.10.1"
- yarn
Snack or a link to a repository
https://pastebin.com/WLbC7D4Y
Reanimated version
3.10.1
React Native version
0.74.1
Platforms
Android, iOS
JavaScript runtime
None
Workflow
None
Architecture
None
Build type
None
Device
None
Device model
No response
Acknowledgements
Yes
Hello, we have the exact same crash.
The stack trace:
TypeError: undefined is not a function
at useEffect$argument_0(node_modules/react-native-reanimated/src/reanimated2/hook/useScrollViewOffset.ts:101:46)
The line that crash in useScrollViewOffset.ts:
scrollRefTag.current = animatedRef.getTag();
The crash happen because the ref given to useScrollViewOffset is not "connected" to a scroll view.
In the following snack, if we were to connect aref to an AnimatedScrollView, the crash would go away.
Snack reproduction: https://snack.expo.dev/@mhammerc/4d8044
Update:
I think this is already fixed in this commit.
https://github.com/software-mansion/react-native-reanimated/commit/11006a9909e2bed7e6ab0c5192dc5e35978eed1c
I'm also getting this issue with SDK 51.0.11. Worked fine on SDK 50.0.14.
am also faced same issue in the SDK 51, but its fixed in this way
// Initialize hooks at the top level
const scrollRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useSharedValue(0);
const scrollHandler = useAnimatedScrollHandler(event => {
scrollOffset.value = event.contentOffset.y;
});
<Animated.ScrollView
ref={scrollRef}
onScroll={scrollHandler} >
.................................
</Animated.ScrollView>
Hey guys, @mhammerc is right. The mentioned commit fixes the issue (lets you pass null to useScrollViewOffset) but you need to follow the API 😄. If you don't want to instantly pass an AnimatedRef to a component (for whatever reason), you can just control what goes into the hook using states, like this:
const scroll = useScrollViewOffset(refConnectedState ? aref : null);
In general, I'd suggest you rather conditionally passed refs or null to the hook than conditionally assign refs to components 😄
onScroll={scrollHandler}
I get this error
ERROR TypeError: _this.props.onScroll is not a function (it is Object), js engine: hermes
if i use your code. Its not crash at init but after scroll
@XxQuickSilverZz btw, expo 51 has a version of Reanimated that has a bug in there. I suggest manually bumping the version to 3.13.0
you can use this approach too
const scrollRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useScrollViewOffset(scrollRef.current ? scrollRef: null);
same error
I get this error always after try this @MULERx solution.
ERROR TypeError: _this.props.onScroll is not a function (it is Object), js engine: hermes
After scroll i get this error.l
i dont use expo anymore. Always the same ****. After a Major Update nothing works anymore.
Just a quick FYI, in case anyone is still driving through here. This error may also happen when your component returns something else than the ScrollView in different renders.
For example:
const scrollRef = useAnimatedRef<Animated.ScrollView>()
const scrollOffset = useScrollViewOffset(scrollRef)
if (!params) {
return <Unmatched />;
}
if (!otherCondition) {
return null;
}
return (
<Animated.ScrollView
ref={scrollRef}
scrollEventThrottle={1000 / 60} // ~16fps
>
// ...
</Animated.ScrollView>
)
In that case you may try the following:
const scrollOffset = useSharedValue(0);
const scrollHandler = useAnimatedScrollHandler({
onScroll: ({ contentOffset }) => {
scrollOffset.value = contentOffset.y;
},
});
return (
<Animated.ScrollView
onScroll={scrollHandler}
scrollEventThrottle={1000 / 60} // ~16fps
>
// ...
</Animated.ScrollView>
)
To solve this, you can just try this:
const scrollRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useScrollViewOffset(scrollRef.current ? scrollRef : null);