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
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.
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?
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>
);
}
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
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.