Crash when use customAnimation
Describe the bug here is the code:
const renderItem = useCallback(({ item }: { item: IDayData; index: number }) => {
return <View style={{ width: windowWidth * 0.9, height: 500, backgroundColor: 'red' }} />;
}, [])
<Carousel
vertical={true}
width={windowWidth * 0.9}
height={500}
customAnimation={(value: number) => {
'worklet';
const zIndex = interpolate(
value,
[-3, -2, -1, 0, 1, 2, 3],
[0, 1, 3, 5, 3, 1, 0],
Extrapolation.CLAMP,
);
return {
// ...animatedTransform,
zIndex,
} as any;
}}
modeConfig={{
parallaxScrollingScale: 0.9,
parallaxScrollingOffset: 50,
}}
data={data}
renderItem={renderItem}
/>
To Reproduce Yesterday, my component still running well. But today it just gonna die when scrolling. Just crash without log anything. i findout it crash because customAnimation, when i comment it can run.
Someone can help...
Versions "@expo/vector-icons": "^15.0.3", "@legendapp/list": "^2.0.14", "@react-native-async-storage/async-storage": "^2.2.0", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/elements": "^2.6.3", "@react-navigation/native": "^7.1.8", "@react-three/drei": "^10.7.7", "@react-three/fiber": "^9.4.0", "@types/qs": "^6.14.0", "axios": "^1.13.2", "expo": "~54.0.25", "expo-asset": "~12.0.10", "expo-clipboard": "^8.0.7", "expo-constants": "~18.0.10", "expo-font": "~14.0.9", "expo-gl": "^16.0.7", "expo-haptics": "~15.0.7", "expo-image": "~3.0.10", "expo-linear-gradient": "^15.0.7", "expo-linking": "~8.0.9", "expo-router": "~6.0.15", "expo-splash-screen": "~31.0.11", "expo-status-bar": "~3.0.8", "expo-symbols": "~1.0.7", "expo-system-ui": "~6.0.8", "expo-three": "^8.0.0", "expo-web-browser": "~15.0.9", "i18next": "^25.6.2", "lottie-react-native": "^7.3.4", "qs": "^6.14.0", "react": "19.1.0", "react-dom": "19.1.0", "react-i18next": "^16.3.1", "react-native": "0.81.5", "react-native-gesture-handler": "~2.28.0", "react-native-reanimated": "~4.1.1", "react-native-reanimated-carousel": "^4.0.3", "react-native-safe-area-context": "~5.6.0", "react-native-screens": "~4.16.0", "react-native-svg": "15.12.1", "react-native-web": "~0.21.0", "react-native-worklets": "0.5.1", "three": "^0.181.0", "zustand": "^5.0.8"
Smartphone:
- Device: simulator and real device 15prm
- OS: 18.5
Hi @khanwilson! I'm Dosu and I’m helping the react-native-reanimated-carousel team.
Your crash is caused by returning a non-integer zIndex in your customAnimation. React Native requires zIndex to be an integer—using a float (from interpolate) can cause native crashes, especially on iOS and with the new architecture. To fix this, wrap your zIndex calculation with Math.round() before returning it [source].
Also, your customAnimation should include a transform property (like translateY for vertical carousels) to ensure items animate and position correctly. Here’s how you can update your code:
customAnimation={(value: number) => {
'worklet';
const zIndex = Math.round(
interpolate(
value,
[-3, -2, -1, 0, 1, 2, 3],
[0, 1, 3, 5, 3, 1, 0],
Extrapolation.CLAMP,
)
);
const translateY = interpolate(
value,
[-3, -2, -1, 0, 1, 2, 3],
[-1500, -1000, -500, 0, 500, 1000, 1500], // adjust based on your item height
Extrapolation.CLAMP,
);
return {
transform: [{ translateY }],
zIndex,
};
}}
Best practices: always use 'worklet', round zIndex, and include transform (and optionally opacity) in your animated style [source] [source].
If you still see crashes, check that you have 'react-native-reanimated/plugin' in your babel.config.js, import 'react-native-gesture-handler' at the top of your entry file, and try resetting the metro cache and reinstalling the app [source].
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
const renderItem = useCallback(({ item }: { item: IDayData; index: number }) => {
return <View style={{ width: windowWidth * 0.9, height: 300, backgroundColor: 'red' }} />;
}, [isScrolling, onPressShowAll])
return <>
<Carousel
vertical={true}
width={windowWidth * 0.9}
height={525}
scrollAnimationDuration={600}
onScrollStart={() => {
setIsScrolling(true)
}}
onScrollEnd={() => {
closure.delay(() => {
setIsScrolling(false)
}, 50)
}}
customAnimation={(value: number) => {
'worklet';
const contentAbsoluteTop = 100; // 30% of item height = 90px
// Scale: value = 2 (item ở giữa) = 1, các item khác scale nhỏ hơn
const scale = interpolate(
value,
[-3, -2, -1, 0, 1],
[0.7, 0.8, 0.9, 1, 0.9,],
Extrapolation.CLAMP,
);
// TranslateY: value = 2 = 0, -1,0,1 dịch lên trên (đã qua), 3,4,5 dịch xuống dưới (sắp đến)
const translateY = interpolate(
value,
[-3, -2, -1, 0, 1],
[0, -55, -25, 0, 25,],
Extrapolation.CLAMP,
) + contentAbsoluteTop;
// RotateX: value = 2 = 0, -1,0,1 xoay dương (đã qua), 3,4,5 xoay âm (sắp đến)
const rotateX = interpolate(
value,
[-3, -2, -1, 0, 1],
[-90, -10, -5, 0, -5,],
Extrapolation.CLAMP,
);
const transform = {
transform: [
{ scale },
{ translateY },
{ perspective: 550 },
{ rotateX: `${rotateX}deg` },
],
};
const animatedTransform = withAnchorPoint(
transform,
{ x: 0, y: 0.5 },
{
width: baseOptions.width,
height: baseOptions.height,
},
);
const zIndex = interpolate(
value,
[-3, -2, -1, 0, 1, 2, 3],
[0, 1, 3, 5, 3, 1, 0],
Extrapolation.CLAMP,
);
return {
...animatedTransform,
zIndex,
} as any;
}}
modeConfig={{
parallaxScrollingScale: 0.9,
parallaxScrollingOffset: 50,
}}
data={data}
renderItem={renderItem}
/>
i try with this but still got crash without any log... :(
Your crash is almost certainly caused by returning a non-integer zIndex in your customAnimation. React Native requires zIndex to be an integer—using a float (from interpolate) will silently crash the app, especially on iOS and with the new architecture. You need to wrap your zIndex calculation with Math.round() before returning it in your style object. For example:
const zIndex = Math.round(
interpolate(
value,
[-3, -2, -1, 0, 1, 2, 3],
[0, 1, 3, 5, 3, 1, 0],
Extrapolation.CLAMP,
)
);
Return this rounded zIndex in your style object. This fix is confirmed to resolve silent crashes in multiple cases (source, source, source).
Also, try temporarily removing withAnchorPoint and any 3D transforms (like perspective and rotateX) to see if the crash persists. If baseOptions.width or baseOptions.height are undefined, withAnchorPoint could return an invalid style and crash the app. Start with a minimal working customAnimation like this:
customAnimation={(value) => {
'worklet';
const translateY = interpolate(value, [-3, -2, -1, 0, 1], [-150, -100, -50, 0, 50], Extrapolation.CLAMP);
const scale = interpolate(value, [-3, -2, -1, 0, 1], [0.7, 0.8, 0.9, 1, 0.9], Extrapolation.CLAMP);
const zIndex = Math.round(interpolate(value, [-3, -2, -1, 0, 1], [0, 1, 3, 5, 3], Extrapolation.CLAMP));
return {
transform: [{ translateY }, { scale }],
zIndex,
};
}}
If this works, add your transforms back one by one to isolate the cause.
Finally, double-check that you have 'react-native-reanimated/plugin' in your babel.config.js, import 'react-native-gesture-handler' at the top of your entry file, and that your package versions are compatible (source). If you still see crashes, try resetting the metro cache and reinstalling the app.
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
This looks like a usage issue rather than a bug in the library. So the Dosu's answer makes sense to me.
Please try rounding the value (e.g. Math.round or Math.floor) and see if that resolves the issue.
I’ll mark this issue as usage / needs reproduction for now. Feel free to reopen with a minimal reproducible example if the problem persists.