gave up gave up - 10 days ago 5
React JSX Question

Removing children from Array inside ScrollView always deletes last item

I have

<ScrollView horizontal={true} >
{this.state.images.map((uri,i) =>
<Thumb key={i} number={i} uri={uri} onDelete ={this.deleteImage.bind(this)} /> )}
</ScrollView>


Here each
Thumb
class has
Image
. Whenever I click on the image it is required to be deleted from the
ScrollView
.

My Thumb component looks like this

class Thumb extends React.Component {
constructor(props){
super(props);

this.state = {
show : false
}
}


shouldComponentUpdate(nextProps, nextState) {
console.log(nextProps,'nextprops')
return false;
}
render() {
return (
<View style={[styles.button ]}>


<View style={[{position:'relative'},styles.img]} >
<View style={{position:'absolute'}}>
<Image style={styles.img} source={{uri:this.props.uri.path}}/>
</View>

<View style={[styles.img , {position:'absolute',alignItems:'center',justifyContent:'center',opacity:1}]}>

<TouchableHighlight onPress = {() => {this.props.onDelete(this.props))}}>
<Icon name="close" size = {30} color="white"/>
</TouchableHighlight>
</View>
</View>

</View>
);
}
}


and i'm trying to delete

deleteImage(deleteProp){
// console.log(_scrollView)
// _scrollView.props.children.splice(deleteProp.number,1)
// console.log(_scrollView)
console.log(deleteProp,'prop from delete method');
console.log(this.state.images ,'before')
let images = this.state.images;
console.log(images.splice(deleteProp.number ,1),'splice data');
this.setState({images : images});
console.log(this.state.images,'after')
if(this.state.images.length == 0 ){
this.setState({loading:false})
}
}


How should I achieve this?

I tried deleting the corresponding state wise Image object but its always deletes the last image of the ScrollView(or last Thumb component).

I'm new to react-native and Android I don't know this is possible with ScrollView. Please suggest me the correct method.

Answer

This is a pretty common issue with confusing the role keys play in Components. We think of keys just as a unique identifier for the dynamically generated components. But it also serves as a means for React to know which components need to be redrawn.

As such, I would advise changing your key to be something unique to the image itself, not the position.

<Thumb key={uri.path} number={i} uri={uri} onDelete={this.deleteImage.bind(this)} />

Here's the official docs on keys.

The key only has to be unique among its siblings, not globally unique. As a last resort, you can pass item's index in the array as a key. This can work well if the items are never reordered, but reorders will be slow. (emphasis mine).

This is another good article about why keys are important.

Also, when you have arrays that are generating components, I like to "preload" the functions to not need indexes, ids, etc, passed up to it.

// original component
<Thumb key={i} number={i} uri={uri} onDelete={this.deleteImage.bind(this)} />
// updated function by adding index to bind params and unique key
<Thumb key={uri.path} number={i} uri={uri} onDelete={this.deleteImage.bind(this,i)} />

That way, when you want to delete you can simply call this.props.onDelete(). Just a preference but I think it's cleaner.

Comments