Segmented control tab with multiple list view overlapping data - react-native

I am working on a react native application in which I have used Segmented control tab which works for both Android and iOS. I am using this github component for segmented tabs https://www.npmjs.com/package/react-native-segmented-control-tab
Here is my code sample :-
<View>
<SegmentedControlTab
values={['Tab 1', 'Tab 2']}
selectedIndex={this.state.selectedIndex}
onTabPress={this.handleIndexChange}
/>
<SearchBox
placeholder={this.state.selectedIndex === 0 ? 'Tab 1' : 'Tab 2'}
onFilterChange={this.onFilterChange}
filterPress={this.filterPress}
/>
{ this.state.selectedIndex === 0 ?
<ListView
style={styles.list}
dataSource={this.state.dataSource}
renderRow={user => (
<UserListRow
{...{ user }}
/>)}
refreshControl={
<RefreshControl
refreshing={false}
onRefresh={() => this._onRefresh()}
/>
}
onEndReached={() => this._onEndReached()}
onEndReachedThreshold={10}
enableEmptySections={true}
/>
:
<ListView
style={styles.list}
dataSource={this.state.dataSourceJobs}
renderRow={job => (
<JobListRow
{...{ job }}
/>
)}
refreshControl={
<RefreshControl
refreshing={false}
onRefresh={() => this._onRefresh()}
/>
}
onEndReached={() => this._onEndReached()}
onEndReachedThreshold={10}
enableEmptySections={true}
/>
}
</View>
Everything is working as I expected till the time I am not scrolling the Tab 1 OR Tab 2. Data gets overlap while scrolling down for pagination. e.g Data inside Tab 1 moves to Tab 2 and vice versa.
I am using below code for updating dataSource of list view.
componentWillReceiveProps({ data }) {
this.updateDataSource(data.tab1);
this.updateDataSourceJobs(data.tab2);
}
Here are some other usefult methods:-
updateDataSource(users) {
this._data = _.uniqBy(this._data.concat(users.toJS()), 'id');
this.setState({
dataSource: this.state.dataSource.cloneWithRows(
this._data
)
});
}
updateDataSourceJobs(jobs) {
this._jobData = _.uniqBy(this._jobData.concat(jobs.toJS()), 'id');
this.setState({
dataSourceJobs: this.state.dataSourceJobs.cloneWithRows(
this._jobData
),
});
}
I am not able to understand the issue is with Segmented control tab or with list view.
Also, If I am scrolling Tab 1 the other tab also gets scrolled.
Any help would be appreciated!

Related

ScrollView inside Actionsheet doesn't scroll in android

Facing an issue where scrolling doesn't take effect in android but, in IOS works fine.
I tried using contentContainerStyle and wrapping the Scrollview with View but nothing changed.
<Actionsheet isOpen={isOpen} onClose={onClose}>
<Actionsheet.Content position={"absolute"} bottom={"0"}>
<Stack space={8} width={"100%"} px={"4"} py={"5"}>
<PrimaryText fontWidth={"bold"} fontSize={"lg"}>
{question}
</PrimaryText>
<Input
// double bind with the hook
value={searchInput}
onChangeText={(value) => setSearchInput(value)}
// style the input field
placeholder={t("commonComponents.search")}
variant={"unstyled"}
p={"3"}
textAlign={I18nManager.isRTL ? "right" : "left"}
fontFamily={fonts[i18n.language].medium}
fontSize={16}
borderWidth={"1"}
borderColor={colors.gray[200]}
InputRightElement={
<Box mr={"2"}>
<EvilIcons name="search" size={30} color={colors.gray[400]} />
</Box>
}
/>
<HStack justifyContent={"space-between"}>
<PrimaryText fontWidth={"medium"} fontSize={"sm"}>
{t("commonComponents.allItems")}
</PrimaryText>
<PrimaryText fontSize={"sm"} color={colors.gray[400]}>
{t("commonComponents.selected", {
selLength: selectedList.length,
})}
</PrimaryText>
</HStack>
<ScrollView height={"300"}>
{optionsList
.filter(
(opt) =>
opt.name_en
.toLowerCase()
.includes(searchInput.toLowerCase()) ||
opt.name_ar
.toLowerCase()
.includes(searchInput.toLowerCase())
)
.map((item) => {
return (
<SelectTile
key={item.id}
icon={item.icon}
title={item["name_" + i18n.language]}
isSelected={selectedList.some(
(selItem) => selItem.id === item.id
)}
/>
);
})}
</ScrollView>
</Stack>
</Actionsheet.Content>
</Actionsheet>
This part is the only part I want to scroll to work on.
In the end, I want to achieve multi-select features inside an ActionSheet.

KeyboardAvoidingView, ScrollView and Flatlist in a form

I have a form where I am using KeyboardAvoidingView and ScrollView so that when a user clicks on an input field the screen will scroll to that particular field
Within my form I have an input field that is searchable and I am using a FlatList to display the results for the user to choose from. Currently I am getting the error:
VirtualizedLists should never be nested inside plain ScrollViews
I've looked at many posts around this but am yet to find a solution (unless I've missed something):
1 - How to put FlatList inside of the ScrollView in React-native?
2 - FlatList inside ScrollView doesn't scroll
3 - How to make a FlatList scrollable inside of a ScrollView in react native?
This is what I have so far:
export const SignUpMember = ({navigation}) => {
const renderHeader = formikProps => {
return (
<>
<FormField
keyboardType={'default'}
fieldName={'firstName'}
label={'First Name'}
/>
<FormField
keyboardType={'default'}
fieldName={'lastName'}
label={'Last Name'}
/>
<FormField
onChangeText={text => {
formikProps.values.clubName = text;
searchItems(text);
}}
value={formikProps.values.clubName}
keyboardType={'default'}
fieldName={'clubName'}
label={'Club Name'}
placeholder={'Search Club By Name...'}
/>
</>
);
};
const renderFooter = formikProps => {
return (
<>
<FormField
keyboardType={'phone-pad'}
fieldName={'telephone'}
label={'Telephone'}
/>
<FormField
keyboardType={'email-address'}
fieldName={'email'}
label={'Email'}
/>
<FormField
keyboardType="default"
secureTextEntry={true}
fieldName={'password'}
label={'Password'}
type={'password'}
/>
<FormField
keyboardType="default"
secureTextEntry={true}
fieldName={'passwordConfirmation'}
label={'Confirm Password'}
type={'password'}
/>
<Button
mt="2"
bg="brand.blue"
type="submit"
onPress={formikProps.handleSubmit}>
Sign Up
</Button>
</>
);
};
return (
<KeyboardAvoidingView
keyboardVerticalOffset={headerHeight}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<ScrollView
_contentContainerStyle={styles.container}
nestedScrollEnabled={true}>
<Box p="1" py="8" w="90%" maxW="290">
<VStack space={3} mt="5">
<Formik
initialValues={initialFormValues}
onSubmit={values => handleFormSubmit(values)}
validationSchema={userValidationSchema}>
{formikProps => (
<View>
<FlatList
nestedScrollEnabled={true}
data={flatListData}
renderItem={({item}) => (
<Pressable
onPress={() => {
formikProps.values.clubName = item.name;
setFlatListData([]);
}}>
<Text style={styles.flatList}>{item.name}</Text>
</Pressable>
)}
keyExtractor={item => item.name}
ListHeaderComponent={renderHeader(formikProps)}
ListFooterComponent={renderFooter(formikProps)}
/>
</View>
)}
</Formik>
</VStack>
</Box>
</ScrollView>
</KeyboardAvoidingView>
);
};
export default SignUpMember;
How can I piece this together?

Double tap on a Flatlist React Native

I'm trying to recreate Instagram's double tap on an item and a heart appears for a few seconds. Im currently rendering text items in a flatist (1 item per page) and I want the user to be able to double tap the text section and a heart will appear.
I can't seem to get both the flatList and the animation to work together. Any ideas? In my current code it will only render the flatList and not the Animated.image. I tried wrapping the animated image in an oppress in a touchable without feedback, still no luck
const onDoubleTap = useCallback(() => {
//console.log("tapped");
scale.value = withSpring(1, undefined, (isFinished) => {
if (isFinished) {
scale.value = withDelay(500, withSpring(0));
console.log("Double Tapped");
}
});
}, []);
return (
<TapGestureHandler
numberOfTaps={2}
onActivated={onDoubleTap}
>
<Animated.View>
<FlatList
horizontal={false}
decelerationRate={"fast"}
snapToAlignment={"center"}
snapToInterval={Dimensions.get("screen").height}
data={flatl}
// keyExtractor={(item, index) => `id_${index}`}
style={styles.fullScreen}
renderItem={({ item }) => (
<View style={[{ ...styles.fullHeight }]}>
<Text>{item.name}</Text>
</View>
)}
/>
<AnimatedImage
source={require("../assets/heart.png")}
style={[
styles.image,
rStyle,
]}
resizeMode={"center"}
/>
</Animated.View>
</TapGestureHandler>
);
}

FlatList Weird Behavior after appending new data - multiple automatic scrolling

I have a list of data that shows posts feed, whenever user scrolls, the list automatically scrolls multiple times up or down which results in a very bad UX
tried the workaround provided here:
https://stackoverflow.com/questions/43611485/prevent-flatlist-from-scrolling-when-new-items-are-added#=
but it doesn't seem to work for me.
<FlatList
keyboardDismissMode = 'on-drag'
keyboardShouldPersistTaps = 'always'
getItemLayout={(data, index) => (
{length: 575, offset: 575 * index, index}
)}
onScroll = {(event) => {
this.flatListOffset = event.nativeEvent.contentOffset.y
this.setState({
scrollOffset: event.nativeEvent.contentOffset.y
})
}}
contentContainerStyle={{
flexGrow: 1,
width: Dimensions.get('window').width
}}
refreshControl={
<RefreshControl
progressViewOffset={120}
refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}
ref={(feedView) => (this.feedView = feedView)}
data={this.state.feed}
onEndReached={() => {
if (this.state.hasNextPage && !this.state.loadingMore) {
this.paginateFeed()
}
}}
ListHeaderComponent={this._renderCirclesBar}
ListEmptyComponent={this._renderEmptyState}
ListFooterComponent={() =>
!this.state.loadingMore ? null : (
<ActivityIndicator color="#2962FF" size="large" />
)
}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
then at some point:
this.setState({ feed: this.state.feed.concat(....) })
a GIF explaining the issue:
https://gifyu.com/image/9gDD
User PureComponent for rendering and set prop disableVirtualization={true} in flatlist

ReactNative - FlatList not updated until scroll

I have a problem with FlatList component which does not update until scrolled.
I tried add log to renderItem and keyExtractor both methods called with correct data but list didn't update.
Here is a render method:
render() {
const messages = this.props.messages
const message = this.props.message
return (
<View style={[styles.container]}>
<FlatList
ref={"flatList"}
contentContainerStyle={styles.list}
data={messages}
renderItem={(listItem) => {
return <MessageBuble message={listItem.item}/>
}}
keyExtractor={(item: Message) => {
return item.id
}}
/>
<View style={[styles.textInputContainer]}>
<TextInput
style={styles.textInput}
value={message}
multiline={true}
onChangeText={this.props.messageChanged}
/>
<Button title={"Odeslat"} onPress={() => {
if (this.props.sendMessage) {
this.props.sendMessage(this.props.message)
}
}}/>
</View>
</View>
)
}
Add extraData in FlatList and retry
<FlatList
extraData={this.props}
....
Tried the extraData, but that does not work.
There was an issue on Android where content was not visible when I returned back from another page to home screen (where the flatlist was present). The content was visible when I scrolled it a bit.
I assigned the main list to the extraData attribute, and could see that it changed in size via console logs. But the content remained invisible. Finally, used
onContentSizeChange={() => {
if (list.length > 0) {
ref.current.scrollToOffset({ animated: true, x: 0 });
}
}}
and it worked.