Closed ccannell closed 4 years ago
Hey @ccannell I can almost guarantee this isn't an issue with this library. If you look at the examples in this repo you'll notice I use the useState
hook to update state when a row is deleted and it definitely does not change the scroll position whatsoever.
If you want to post more code here I'd be happy to try and help diagnose your issue though
Here is the code in question.
Note. I'm using Redux connect as well.
I am trying to implement a scroll to top button that only appears when the list view is scrolled away from the top. I call setIsScrolling when the list view scrolls and then show a scroll to top button.
Hey @ccannell very strange that you're seeing this behavior. I set up an example as close to your component as possible and this is what I came up with and it seems to be working just fine.
I'm not sure how to help from here.. maybe look through and try to find differences in your code and this code below. Maybe show me a recording and that might help..?
Here is the code for this example:
import React, { useState } from 'react';
import {
StyleSheet,
Text,
TouchableOpacity,
TouchableHighlight,
View,
} from 'react-native';
import SwipeListView from '../SwipeListView';
let listViewRef = null;
export default function Basic() {
const [listData, setListData] = useState(
Array(20)
.fill('')
.map((_, i) => ({ key: `${i}`, text: `item #${i}` }))
);
const [isScrolling, setIsScrolling] = useState(false);
const closeRow = (rowMap, rowKey) => {
if (rowMap[rowKey]) {
rowMap[rowKey].closeRow();
}
};
const deleteRow = (rowMap, rowKey) => {
closeRow(rowMap, rowKey);
const newData = [...listData];
const prevIndex = listData.findIndex(item => item.key === rowKey);
newData.splice(prevIndex, 1);
setListData(newData);
};
const renderItem = data => (
<TouchableHighlight
onPress={() => console.log('You touched me')}
style={styles.rowFront}
underlayColor={'#AAA'}
>
<View>
<Text>I am {data.item.text} in a SwipeListView</Text>
</View>
</TouchableHighlight>
);
const renderHiddenItem = (data, rowMap) => (
<View style={styles.rowBack}>
<Text>Left</Text>
<TouchableOpacity
style={[styles.backRightBtn, styles.backRightBtnLeft]}
onPress={() => closeRow(rowMap, data.item.key)}
>
<Text style={styles.backTextWhite}>Close</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.backRightBtn, styles.backRightBtnRight]}
onPress={() => deleteRow(rowMap, data.item.key)}
>
<Text style={styles.backTextWhite}>Delete</Text>
</TouchableOpacity>
</View>
);
return (
<View style={styles.container}>
<SwipeListView
listViewRef={ref => (listViewRef = ref)}
data={listData}
renderItem={renderItem}
renderHiddenItem={renderHiddenItem}
leftOpenValue={75}
rightOpenValue={-150}
previewRowKey={'0'}
previewOpenValue={-40}
previewOpenDelay={3000}
onScroll={e => {
setIsScrolling(e.nativeEvent.contentOffset.y > 0);
}}
onScrollToTop={() => setIsScrolling(false)}
scrollEventThrottle={1}
/>
{isScrolling && (
<TouchableOpacity
onPress={() =>
listViewRef.scrollToOffset({
x: 0,
y: 0,
animated: true,
})
}
style={{
alignItems: 'center',
justifyContent: 'center',
height: 40,
width: 200,
position: 'absolute',
bottom: 30,
right: 30,
backgroundColor: 'red',
}}
>
<Text style={{ color: 'white' }}>TOP</Text>
</TouchableOpacity>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
flex: 1,
},
backTextWhite: {
color: '#FFF',
},
rowFront: {
alignItems: 'center',
backgroundColor: '#CCC',
borderBottomColor: 'black',
borderBottomWidth: 1,
justifyContent: 'center',
height: 50,
},
rowBack: {
alignItems: 'center',
backgroundColor: '#DDD',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: 15,
},
backRightBtn: {
alignItems: 'center',
bottom: 0,
justifyContent: 'center',
position: 'absolute',
top: 0,
width: 75,
},
backRightBtnLeft: {
backgroundColor: 'blue',
right: 75,
},
backRightBtnRight: {
backgroundColor: 'red',
right: 0,
},
});
@ccannell Okay one other thing I did notice is that you have two different SwipeListViews depending on which tab you're on. Is it possible you're losing scroll position because the tabs are changing? Maybe something about the using the same ref to track both SwipeListViews is causing problems? Again, a recording of the issue might help
@jemise111 Thanks for the example. I'm going to do some more investigating.
@jemise111 Thank you for the help. I tested again and it IS working. I'm using expo and hot reloading. I suspect the app was in a weird state. When I ran it again fresh it worked as it should. Thank you very much for the help.
Ah gotcha, yeah I find HMR Is really great for tweaking styles. But for changes in functionality it can get wonky. Glad it's working now.
Also @ccannell complete side note but after you linked your codebase I was looking around the Connect Our Kids website and noticed there's a section for Technology Volunteers. If you have the time I'd love to hear more about that if you're looking for more volunteers. My email is jesse.sessler@gmail.com, thanks!
First off. Great library. Thank you for taking the time to develop and maintain it!
When I change the state with
useState
the component renders again and the list looses its scrolled position. Is there a way to preserve its scroll position?