rn-tourguide
rn-tourguide copied to clipboard
ERROR while scrolling back outside the refferred scrollview
in my code zone 1 and 2 works perfectly with scroll thanks to @xcarpentier but when i come to zone 3 which is outside the scroll view i get an error which is telling me
`view <RCTShadowView: 0x7f8efd4bdb90; viewName: RCTView; reactTag: 105; frame: {{0, 0}, {234, 24}}> (tag #105) is not a descendant of <RCTShadowView: 0x7f8efd4725c0; viewName: RCTScrollView; reactTag: 669; frame: {{0, 108}, {390, 657}}> (tag #669)
RCTMeasureLayout RCTUIManager.m:1392 -[RCTUIManager measureLayout:relativeTo:errorCallback:callback:] invoking_ -[NSInvocation invoke] -[NSInvocation invokeWithTarget:] -[RCTModuleMethod invokeWithBridge:module:arguments:] facebook::react::invokeInner(RCTBridge*, RCTModuleData*, unsigned int, folly::dynamic const&, int, (anonymous namespace)::SchedulingContext) facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int)::$_0::operator()() const invocation function for block in facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int) _dispatch_call_block_and_release _dispatch_client_callout _dispatch_lane_serial_drain _dispatch_lane_invoke _dispatch_workloop_worker_thread _pthread_wqthread start_wqthread `
my code is like that :
` <View style={{ width: '60%' }}> <TourGuideZone zone={3} text={mainTourValues[2].appTutorialResource.title} borderRadius={16} > <TouchableOpacity style={[styles.profileImage]} onPress={() => toggle()}> <Text style={styles.dropdownButtonTextStyle}> {patientDetail?.data?.fullName ?? ''} </Text> <IconBottomArrow></IconBottomArrow> </TouchableOpacity> </TourGuideZone> </View> <View style={styles.rigthmenu}> <TouchableOpacity style={{ paddingTop: 10, }} onPress={() => { navigation.navigate('BasketScreen'); }}>
<IconBasket />
{userBasketCount > 0 && (
<LinearGradient
colors={['#253FC4', '#000D4F']}
style={{
position: 'absolute',
top: 0,
right: 0,
width: 22,
height: 22,
borderRadius: 11,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text style={{ ...FONTS.f1, color: 'white' }}>
{userBasketCount}
</Text>
</LinearGradient>
)}
</TouchableOpacity>
<TouchableOpacity
style={{
paddingTop: 10,
}}
onPress={() => {
navigation.navigate('NotificationScreen');
}}>
<IconNotification />
{userNotificationCount > 0 && (
<LinearGradient
colors={['#253FC4', '#000D4F']}
style={{
position: 'absolute',
top: 0,
right: 0,
width: 22,
height: 22,
borderRadius: 11,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text style={{ ...FONTS.f1, color: 'white' }}>
{userNotificationCount}
</Text>
</LinearGradient>
)}
</TouchableOpacity>
<TouchableOpacity
style={{
paddingTop: 10,
}}
onPress={() => {
handleScaleChange();
}}>
<IconMenu />
</TouchableOpacity>
</View>
</View>
<ScrollView
ref={(r) => { scrollRef.current = r }}
contentContainerStyle={{ flexGrow: 1 }}
scrollEventThrottle={16}
keyboardShouldPersistTaps={'always'}
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={loadDashboardDetail}
/>
}
>
<View style={styles.container}>
<View style={styles.section}>
<TextInput
style={styles.input}
value={search}
placeholder={strings.searchDasboardPlaceHolder}
onChangeText={text => setSearch(text)}
keyboardType="default"
onSubmitEditing={() => {
navigation.navigate('SearchHospitalSectionScreen', {
searchText: search,
});
setSearch('');
}}
/>
</View>
<View>
<TourGuideZone
zone={1}
text={mainTourValues[0].appTutorialResource.title}
borderRadius={16}
>
<SwiperFlatList
autoplay
autoplayDelay={3}
autoplayLoop
index={0}
contentContainerStyle={{ marginHorizontal: 15 }}
borderRadius={15}
showPagination
keyExtractor={(item, index) => index.toString()}
data={dashboardData?.sliderList}
paginationStyleItemActive={styles.paginationStyleItemActive}
paginationStyleItemInactive={styles.paginationStyleItemInactive}
paginationActiveColor={'#B1292F'}
paginationDefaultColor={'#F4888C'}
renderItem={({ item }) => (
<Pressable
key={item.key}
style={styles.child}
onPress={async () => {
const result = await getSliderDetailById(item.id);
navigation.navigate('SliderDetailScreen', {
item: result?.data?.sliderResource,
});
}}>
<Image
style={styles.imageStyle}
resizeMode="contain"
source={{
uri: item?.sliderResource?.image,
}}
/>
</Pressable>
)}
/>
</TourGuideZone>
</View>
{/* Hizmet Paketleri */}
{serviceData?.length !== 0 && (
<>
<View style={styles.serviceView}>
<Text
style={[
styles.textSizeLarge,
styles.textBlue,
styles.textBold,
]}>
{strings.servicePackages}
</Text>
<Text
onPress={() => navigation.navigate('PackageScreen')}
style={[
styles.textSizeMedium,
styles.textUnderline,
styles.textBlue,
]}>
{strings.seeAll}
</Text>
</View>
<View style={styles.shadow}>
<FlatList
data={serviceData}
renderItem={item => (
<RenderPackageList {...item} getDetail={getDetail} />
)}
contentContainerStyle={styles.flatlistContent}
keyExtractor={(item, index) => index.toString()}
horizontal={true}
scrollEnabled
showsHorizontalScrollIndicator={false}
/>
</View>
</>
)}
{/* Randevular */}
<>
<View ref={stepRef2} style={styles.serviceView}>
<Text
style={[
styles.textSizeLarge,
styles.textBlue,
styles.textBold,
]}>
{strings.upcomingAppointments}
</Text>
<TouchableOpacity
onPress={() => navigation.navigate('AppointmentListScreen')}>
<Text
style={[
styles.textSizeMedium,
styles.textUnderline,
styles.textBlue,
]}>
{strings.seeAll}
</Text>
</TouchableOpacity>
</View>
<View
style={{
height:
dashboardData?.appointments?.futureList.length !== 0
? 240
: 'auto',
}}>
<>
{dashboardData?.appointments?.futureList.length === 0 ? (
<View style={styles.flexDirectionRow}>
<TourGuideZone
zone={2}
text={mainTourValues[1].appTutorialResource.description}
borderRadius={16}
>
<TouchableOpacity
style={[
styles.appointmentFirstItem,
styles.alignSelf,
styles.alignItems,
styles.shadow,
]}
onPress={() =>
navigation.navigate('AppointmentScreen')
}>
<IconMakeAppointment />
<Text style={styles.appointmentText}>
{strings.appointment}
</Text>
</TouchableOpacity>
</TourGuideZone>`
Hey i wasn’t able to fix it but i made some hacky solution that work for me if you want to use. the only changes are made in TourGuideProvider.tsx change the if in setCurrentStep to enter the block only if the step order is one of thus in the scrollView also check step. i will note that there is very small dealy when going to the first element in the scroll but not something that seems to be a problem. for example my code look like this:
const setCurrentStep = async (key: string, step?: IStep) =>
new Promise<void>(async (resolve) => {
if (step && (step.order === 3 || step.order === 4)) {
await step.wrapper.measureLayout(
findNodeHandle(scrollRef.current),
(_x: number, y: number, _w: number, h: number) => {
const yOffsett = y > 0 ? y - h / 2 : 0
scrollRef.current.scrollTo({ y: yOffsett, animated: false })
},
)
setTimeout(() => {
updateCurrentStep((currentStep) => {
const newStep = { ...currentStep }
newStep[key] = step
eventEmitter[key]?.emit('stepChange', step)
return newStep
})
resolve()
}, 0);
}
else {
updateCurrentStep((currentStep) => {
const newStep = { ...currentStep }
newStep[key] = step
eventEmitter[key]?.emit('stepChange', step)
return newStep
})
resolve()
}
})
if you have multiple tours you can add the tourkey to the if statment and adjust it so it work for each tour(didnt try this yet). after this i notice when i restared the tour i get an unhandle promise that stuck my simulator that is because scrollRef got undefined on the second tour i am gussing it because the poor handling of my part or something to do to the code structure to solve this i removed the if
if (!scrollRef) {
setScrollRef(_scrollRef)
}
to just
setScrollRef(_scrollRef)
this seems to work for me if you want to use it or have suggestions to make it better it much appreciated.
i solved it by using multiple tour guides , but i am surprised tour guide doesnt work by only position . React should release a core package about it i think :D
@nihatt Could you fix it?
@navaspavil yes , i used multiple guides.
and call next guides after the first guide is finished? @nihatt
@Drzaln Yes , giving them each id's and calling them 1by1 helped me