react-native-ui-lib
react-native-ui-lib copied to clipboard
Expo SDK 54 - Progress Bar Error
Description
After upgrading to Expo SDK 54 and react native 19, Progress bar is giving an error : [TypeError: Cannot read property 'props' of undefined]
Related to
- [ x ] Components
- [ ] Demo
- [ ] Docs
- [ ] Typings
Steps to reproduce
- Use expo SDK 54 and react native 19
- Import progress bar and try to use it
Expected behavior
Progress bar loads and user is able to use the component
Actual behavior
App gives an error
More Info
Code snippet
import { ProgressBar } from "react-native-ui-lib";
<ProgressBar progress={progressBarValue} />
Screenshots/Video
Environment
- React Native version: 19.1.0
- React Native UI Lib version: ^7.46.3
Affected platforms
- [ x ] Android
- [ x ] iOS
- [ ] Web
How did you get it working with SDK 54? I am getting #3805
Same issue in last expo version But you can make the progress bar by yourself
import { View } from '@/components/ui/view';
import { useColor } from '@/hooks/useColor';
import { HEIGHT } from '@/theme/globals';
import React, { useEffect } from 'react';
import { ViewStyle } from 'react-native';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
runOnJS,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';
interface ProgressProps {
value: number; // 0-100
style?: ViewStyle;
height?: number;
onValueChange?: (value: number) => void;
onSeekStart?: () => void;
onSeekEnd?: () => void;
interactive?: boolean;
}
export function Progress({
value,
style,
height = HEIGHT,
onValueChange,
onSeekStart,
onSeekEnd,
interactive = false,
}: ProgressProps) {
const primaryColor = useColor('primary');
const mutedColor = useColor('muted');
const clampedValue = Math.max(0, Math.min(100, value));
const progressWidth = useSharedValue(clampedValue);
const containerWidth = useSharedValue(200); // Default width, will be updated
const isDragging = useSharedValue(false);
// Update animation when value prop changes (only if not dragging)
useEffect(() => {
if (!isDragging.value) {
progressWidth.value = withTiming(clampedValue, { duration: 300 });
}
}, [clampedValue]);
const updateValue = (newValue: number) => {
const clamped = Math.max(0, Math.min(100, newValue));
onValueChange?.(clamped);
};
const handleSeekStart = () => {
isDragging.value = true;
onSeekStart?.();
};
const handleSeekEnd = () => {
isDragging.value = false;
onSeekEnd?.();
};
// Create pan gesture using the new Gesture API
const panGesture = Gesture.Pan()
.onStart(() => {
if (!interactive) return;
runOnJS(handleSeekStart)();
})
.onUpdate((event) => {
if (!interactive) return;
// Calculate new progress based on gesture position
const newProgress = (event.x / containerWidth.value) * 100;
const clampedProgress = Math.max(0, Math.min(100, newProgress));
progressWidth.value = clampedProgress;
runOnJS(updateValue)(clampedProgress);
})
.onEnd(() => {
if (!interactive) return;
runOnJS(handleSeekEnd)();
});
// Create tap gesture for direct seeking
const tapGesture = Gesture.Tap().onStart((event) => {
if (!interactive) return;
runOnJS(handleSeekStart)();
// Calculate progress based on tap position
const newProgress = (event.x / containerWidth.value) * 100;
const clampedProgress = Math.max(0, Math.min(100, newProgress));
progressWidth.value = withTiming(clampedProgress, { duration: 200 });
runOnJS(updateValue)(clampedProgress);
setTimeout(() => {
runOnJS(handleSeekEnd)();
}, 200);
});
// Combine gestures
const combinedGesture = Gesture.Race(panGesture, tapGesture);
const animatedProgressStyle = useAnimatedStyle(() => {
return {
width: `${progressWidth.value}%`,
};
});
const containerStyle: ViewStyle[] = [
{
height: height,
width: '100%' as const,
backgroundColor: mutedColor,
borderRadius: height / 2,
overflow: 'hidden' as const,
},
...(style ? [style] : []),
];
const onLayout = (event: any) => {
containerWidth.value = event.nativeEvent.layout.width;
};
if (interactive) {
return (
<GestureDetector gesture={combinedGesture}>
<Animated.View style={containerStyle} onLayout={onLayout}>
<Animated.View
style={[
{
height: '100%' as const,
backgroundColor: primaryColor,
borderRadius: height / 2,
},
animatedProgressStyle,
]}
/>
</Animated.View>
</GestureDetector>
);
}
return (
<View style={containerStyle} onLayout={onLayout}>
<Animated.View
style={[
{
height: '100%' as const,
backgroundColor: primaryColor,
borderRadius: height / 2,
},
animatedProgressStyle,
]}
/>
</View>
);
}
Note: I refer other UI Lib