"react-native": "0.61.5",
"react-native-draggable-flatlist": "2.1.2"
<DraggableFlatList
//...
ListHeaderComponent={this.props.HeaderComponent}
ListHeaderComponentStyle={styles.header}
//...
/>
const styles = StyleSheet.create({
header: {
paddingTop: 72,
paddingHorizontal: '13%',
marginBottom: 36,
},
//...
});
HeaderComponent is a some view. After some async actions (~3 sec after did mount) HeaderComponent's height will be changed. DraggableFlatList will get wrong offset while any element is dragging (wrong hovering position), so looks like it's not recalculated.
Any suggestions?
Does it correct itself after you drag once? It should remeasure everything when props.data changes: https://github.com/computerjazz/react-native-draggable-flatlist/blob/master/src/index.tsx#L280
In which case, as a workaround, you could update data when your header recalculates, something like:
onRecalculate = () => this.setState(state => ({ data: [...state.data ]}))
@computerjazz
Does it correct itself after you drag once?
Seems like yes, but sometimes it needs not once.
you could update data when your header recalculates
Recreating state data array actually doesn't work for me, even with cloneDeep. Weird things...
@computerjazz Sorry for raw code message.
This is code example based on your own that reproduces my problem (copy-paste should work).
import React, { Component } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import DraggableFlatList from 'react-native-draggable-flatlist';
const exampleData = [...Array(20)].map((d, index) => ({
key: `item-${index}`, // For example only -- don't use index as your key!
label: index,
backgroundColor: `rgb(${Math.floor(Math.random() * 255)}, ${index * 5}, ${132})`,
}));
class Example extends Component {
state = {
data: exampleData,
visible: false,
};
componentDidMount() {
setTimeout(() => {
this.setState({ visible: true, data: [...this.state.data] });
}, 3000);
}
renderItem = ({ item, index, drag, isActive }) => {
return (
<TouchableOpacity
style={{
height: 100,
backgroundColor: isActive ? 'blue' : item.backgroundColor,
alignItems: 'center',
justifyContent: 'center',
}}
onLongPress={drag}
>
<Text
style={{
fontWeight: 'bold',
color: 'white',
fontSize: 32,
}}
>
{item.label}
</Text>
</TouchableOpacity>
);
};
renderHeader = () => {
return (
<View
style={{
minHeight: 150,
backgroundColor: 'green',
}}
>
{this.state.visible && (
<View
style={{
height: 500,
width: 100,
backgroundColor: 'blue',
}}
></View>
)}
</View>
);
};
render() {
return (
<View style={{ flex: 1 }}>
<DraggableFlatList
ListHeaderComponent={this.renderHeader()}
data={this.state.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => `draggable-item-${item.key}`}
onDragEnd={({ data }) => this.setState({ data })}
/>
</View>
);
}
}
export default Example;
Thanks for the example, I see the issue now.
You can invalidate current measurements by setting a new key, so in this case you can force a recalculation by updating your keyExtractor with visible -- something like:
keyExtractor={(item, index) => `draggable-item-${item.key}-${this.state.visible}`}
https://snack.expo.io/@computerjazz/swipetodelete-pkg-header-resize-bug
@computerjazz Thanks a lot, changing keys as working solution is ok for now 馃憤. Will wait for official fix.
Glad it's working! I'll leave this open as it may be useful for others. Feel free to propose an official fix 馃榿.
@ivan-kalinin Thank you for opening this issue and @computerjazz thanks for the fix! This was definitely useful to me. I have a list that can either be auto sorted (i.e. by player name, score, etc) or by dragging and dropping. After changing the list order via auto sort, when trying to drag and drop, the positions were totally off (I believe they were still tied to their old position before being auto sorted). Refreshing the keys on auto sort did the trick. Thanks again!
@computerjazz regarding an official fix, it could be something as simple as adding a new optional prop that will trigger position recalculation (i.e. I pass my state variable in as a prop to DraggableFlatList and the library takes care of refreshing all list item positions when the prop changes). I don't have a suggestion for the exact implementation under the hood, but I could see if I have some time soon to take a better look at source and figure out where that could happen.
@nhuesmann I like that idea -- I think I know where it should go. I'm thinking it could be called layoutInvalidationKey or something along those lines.
@computerjazz Awesome, looking forward to seeing what you come up with!
added layoutInvalidationKey: https://github.com/computerjazz/react-native-draggable-flatlist/commit/bf8eb9d6c2621c085e2fba6ddcaf3d1d7e6e582f
So in the next release, to fix the above example, instead of modifying your keyExtractor you will be able to pass:
<DraggableFlatList
layoutInvalidationKey={`someKey-${this.state.visible}`}
//...other props
/>
Cool, that seems reasonable. To confirm: I can write my standard keyExtractor function returning item.id or item.key, then just provide a string to layoutInvalidationKey that will trigger recalculation?
yep, whenever layoutInvalidationKey changes all items and offsets will be remeasured.
That's perfect. Thanks so much for this awesome library, it seriously saved me so much time and works great!
layoutInvalidationKey added in v2.3.0
Most helpful comment
yep, whenever
layoutInvalidationKeychanges all items and offsets will be remeasured.