react native flatlist jumps items periodically until reaches specific item - react-native

I'm using Flatlist and list items don't have specific height, when I want to scroll to a specific index it's not scrolling to an exact item, and takes a while to go to that item.
this is the video of the problem
when I use this.flatlist.scrollToindex(), I get the error flatlist.scrollToindex() is not a function so I use :
this.flatList.scrollToItem({
animated: true,
item: item,
viewPosition: 0.5,
});
this is the component which has a flatlist inside and doesn't have getItemLayout function:
<CustomFlatList
header={headerComponent}
inverted={renderAsChat || invertedList}
style={[
postStyles.dashboardContainer,
isLonelyPost && { backgroundColor: '#fff' },
]}
loading={loading}
onRefresh={customRefresh === true ? refresh : this.onRefresh}
content={content}
pageTabTitle={pageTabTitle}
renderItem={({ item, key, index }) =>
this.renderPostItem(item, index, pageTabTitle)
}
emptyMessage={emptyMessage}
keyExtractor={(item, key) => this.getItemKey(item)}
loadMore={customLoadMore === true ? loadMore : this.loadMore}
scrollState={this.state.sendPostButtonVisible}
changeScrollState={this.changeScrollState}
navigation={navigation}
onViewableItemsChanged={this.onVideoExitScreen}
enableLoadMore={enableLoadMore && !isLonelyPost}
yOffsetThreshold={1000}
ref={(ref) => { this.flatList = ref; }}
/> : <View />

Related

React native how to render items without using any loder?

I have implemented a delete feature for the image editor app.
Case: If the user added a number of images in edit mode and wants to delete the unnecessary layer of the image from the editor then allows to delete the selected layer from the array.
Issue: when deleted the selected layer from the array the remaining image swaps its position and size to deleted image position and size. Even if I double-check the scale value and position remain the same as I fixed. This issue occurs if am not using the loder and if am using the loder then the image did not swap their position and scale.
Where I handled the states: I am handling the states in the component and I also checked if I handled the states in redux same error occurred. App speed to slow if handled with redux.
Here is my code.
const onDeleteLayerSequence = data => {
let indexing = data.length;
data.forEach(item => {
indexing--;
item.key = indexing;
});
setInputData(data);
setIsDelete(!isDelete);
};
const deleteLayer = index => {
const filterItem = [
...inputData.slice(0, index),
...inputData.slice(index + 1, inputData.length),
];
onDeleteLayerSequence(filterItem);
};
useEffect(() => {
setImageArray(inputData.filter(item => item.type == 'image'));
// setLoader(true);
}, [isDelete]);
return (
<>
<AutoDragSortableView
dataSource={inputData}
parentWidth={util.WP(100)}
childrenWidth={util.WP(100)}
childrenHeight={util.WP(12)}
keyExtractor={(item, index) => item.id}
renderItem={(item, index) => render_item(item, index)}
onDataChange={data => onSelectLayer(data)}
onClickItem={(data, i) => replaceImage(data, i)}
/>
</View>
</DraggablePanel>
<View style={styles.editImageWrapper}>
<ViewShot
ref={reference}
options={{format: 'jpg', quality: 1.0, result: 'base64'}}>
<ImageBackground
style={[
styles.templateContainer,
{backgroundColor: background},
]}
resizeMode="stretch"
source={selectTemplate}>
{isFocused &&
imageArray &&
imageArray.map((item, i) => {
return (
<component.PinchZoomView
minScale={0.1}
maxScale={5}
scale={item.scale}
translateX={item.translateX}
translateY={item.translateY}
data={value =>
modifyValues(value, item.layer, item.key)
}
key={i}
style={[
styles.pinchImagePosition,
{
zIndex: item.key,
},
]}>
<ImageCarousel>
<Image
source={{
uri: item.editImage,
height: util.WP(100),
width: util.WP(100),
}}
key={item}
resizeMode="contain"
/>
</ImageCarousel>
</component.PinchZoomView>
);
})}
</ImageBackground>
</ViewShot>
</View>
</>
)

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

How can I change the numColumns of Flatlist when changing the orientation

I created the function name getOrientation() and put it at useEffect so that whenever I rotate the device, it will rerender the component and show me which orientation the device is.
I also created the variable to determine the orientation by using hook
getOrientation()
const [orientation, setOrientation] = useState("")
const window = useWindowDimensions()
const getOrientation = () => {
if (window.height < window.width) {
setOrientation("LANDSCAPE")
} else {
setOrientation("PORTRAIT")
}
return orientation
}
at useEffect
useEffect(() => {
getOrientation()
})
console.log(orientation)
My problem is that I want to set the numsColumns = 2 in Flatlist (LANDSCAPE) and equals to 1 for the portrait mode but the error popup telling me that I cannot change the numColumns on the fly. What should I do ?
Here is my flatlist
<View style={styles.container}>
<FlatList
contentContainerStyle={{
paddingLeft: insets.left,
paddingRight: insets.right,
}}
data={dishes.dishes}
numColumns={orientation == "LANDSCAPE" ? 2 : 1}
renderItem={({ item, index }) => (
<Tile
style={styles.tileItem}
key={index}
title={item.name}
caption={item.description}
onPress={() => navigation.navigate('Dishdetail_Screen', { dishId: item.id })} // passing infor from one to another screen
// chevron={false}
featured
imageSrc={{
uri: baseUrl + item.image
}}
/>
)}
keyExtractor={item => item.id.toString()} />
</View>
This creepy error
enter image description here
P/s: I'm the fresh React-Native developer. Thanks everyone who is checking my problems
Try adding a key prop to your Flatlist like so with the value being ur orientation:
<FlatList
key={orientation} // add key prop here
contentContainerStyle={{
paddingLeft: insets.left,
paddingRight: insets.right,
}}
data={dishes.dishes}
numColumns={orientation == "LANDSCAPE" ? 2 : 1}
renderItem={({ item, index }) => (
<Tile
style={styles.tileItem}
key={index}
title={item.name}
caption={item.description}
onPress={() => navigation.navigate('Dishdetail_Screen', { dishId: item.id })} // passing infor from one to another screen
// chevron={false}
featured
imageSrc={{
uri: baseUrl + item.image
}}
/>
)}
keyExtractor={item => item.id.toString()} />

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

numColumns breaks scrollToIndex react native FlatList

I'm using react native's FlatList to display a list of items, and also check which items are currently viewable. In my items there's one item which is marked mostUsed if the item is not viewable I display a link at the top, the user can click that and scroll to that item, using scrollToIndex. scrollToIndex works well without setting numColumns, when I set numColumns={2} I get scrollToIndex out of range: 9 vs 4 error.
setScrollIndex = () => {
if (this.state.scrollIndex !== 0) {
return;
}
for (let i = 0; i < this.state.items.length; i++) {
const items = this.state.items;
if (items[i] && items[i].mostUsed) {
this.setState({
scrollIndex: i,
});
}
}
};
// scroll to index function
scrollToIndex = () => {
this.flatListRef.scrollToIndex({
animated: true,
index: this.state.scrollIndex,
});
};
<FlatList
data={this.state.items}
numColumns={2}
keyExtractor={(item, index) => index.toString()}
ref={ref => {
this.flatListRef = ref;
}}
showsVerticalScrollIndicator={false}
onViewableItemsChanged={this.handleViewableItemsChanged}
viewabilityConfig={this.viewabilityConfig}
renderItem={({ item, index }) => (
<Card
title={item.title}
description={item.description}
mostUsed={item.mostUsed}
style={{ width: item.width }}
/>
)}
/>
expo snack
Looks like FlatList's scrollToIndex changes the way it views index if numColumns is higher then 1.
It may be more correct to call it scrollToRowIndex since it does not work on item index in case of multiple columns.
For your case this worked for me on expo:
scrollToIndex = () => {
this.flatListRef.scrollToIndex({
animated: true,
index: Math.floor(this.state.scrollIndex / numColumns),
});
};