Reputation: 45
I'm trying to handle the multi-select with react-native-super-grid
, here is my code :
<GridView
itemDimension={80}
items={items}
style={styles.gridView}
renderItem={item => (
<View style={[styles.itemContainer , { backgroundColor:' transparent '}]}>
<TouchableHighlight style={styles.buttonStyle} onPress={() => this.pressEvent() }>
<Text> {item.image}</Text>
</TouchableHighlight>
<Text style={styles.buttonText}> {item.name}</Text>
</View>)}
/>
I tried using this function :
pressEvent(arr){
if(this.state.pressStatus == false){
this.setState({ pressStatus: true})
this.state.arr.push(arr)
this.setState({ color : 'white'})
} else {
this.setState({ pressStatus: false})
this.setState({ color: 'red'})
}
}
but it somehow doesn't work , can someone help me ?
Thank you .
Upvotes: 0
Views: 766
Reputation: 1
Since GridView has been merged into FlatGrid. Therefore, I've implemented the multi-select option in a pretty easy way. First of all I applied TouchableOpacity on top of the view in the renderItems prop of FlatGrid like this.
<TouchableOpacity
onPress={() => this.selectedServices(item.name)}>
...props
</TouchableOpacity>
SelectedServices:
selectedServices = item => {
let services = this.state.selectedServices;
if (services.includes(item) == false) {
services.push(item);
this.setState({ selectedServices: services });
} else {
let itemIndex = services.indexOf(item);
services.splice(itemIndex, 1);
this.setState({ selectedServices: services });
}
};
Using splice, indexOf, and push, you can easily implement multi-selection.
To change the backgroundColor of the currently selected item, you can apply a check on the backgroundColor prop of the view.
renderItem={({ item, index }) => (
<TouchableOpacity
onPress={() => this.selectedServices(item.name)}
>
<View
style={[
styles.itemContainer,
{
backgroundColor: this.state.selectedServices.includes(
item.name
)
? '#0052cc'
: item.code
}
]}
>
<Text style={styles.itemName}>{item.name}</Text>
</View>
</TouchableOpacity>
)}
Upvotes: 0
Reputation: 2180
This short example should give you an idea what are you doing wrong. The items itself are not aware of the state. So what I would do, I would create a separate child component for grid item and handle press state locally. Then handle parent, which is holding all the item trough callback about the pressed item.
class MyGridView extends Component {
render() {
return (
<GridView
itemDimension={80}
items={items}
style={styles.gridView}
renderItem={item => (
<GridItem
item={item}
onItemPress={selected => {
// set grid view callback
if (selected) {
//if true add to array
this.addToPressedArray(item);
} else {
//false remove from array
this.removeFromPressedArray(item);
}
}}
/>
)}
/>
);
}
// You don't change the state directly, you mutate it trough set state
addToPressedArray = item => this.setState(prevState => ({ arr: [...prevState.arr, item] }));
removeFromPressedArray = item => {
const arr = this.state.arr.remove(item);
this.setState({ arr });
};
}
And the GridItem
class GridItem extends Component {
// starting local state
state = {
pressStatus: false,
color: 'red'
};
// handle on item press
pressEvent = () => {
this.setState(prevState => ({
pressStatus: !prevState.pressStatus, //negate previous on state value
color: !prevState.pressStatus ? 'white' : 'red' //choose corect collor based on pressedStatus
}));
// call parent callback to notify grid view of item select/deselect
this.props.onItemPress(this.state.pressStatus);
};
render() {
return (
<View style={[styles.itemContainer, { backgroundColor: ' transparent ' }]}>
<TouchableHighlight style={styles.buttonStyle} onPress={() => this.pressEvent()}>
<Text> {item.image}</Text>
</TouchableHighlight>
<Text style={styles.buttonText}> {item.name}</Text>
</View>
);
}
}
I also recommend to read about React.Component
lifecycle. Its a good reading and gives you a better understanding how to achieve updates.
Upvotes: 2