Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highlight a selected item in React-Native FlatList

I put together a simple React-native application to gets data from a remote service, loads it in a FlatList. When a user taps on an item, it should be highlighted and selection should be retained. I am sure such a trivial operation should not be difficult. I am not sure what I am missing.

import React, { Component } from 'react'; import {   StyleSheet,   Text,   View,   FlatList,   ActivityIndicator,   Image,   TouchableOpacity, } from 'react-native';  export default class BasicFlatList extends Component {   constructor(props) {     super(props);      this.state = {       loading: false,       data: [],       page: 1,       seed: 1,       error: null,       refreshing: false,       selectedItem:'null',     };   }    componentDidMount() {     this.makeRemoteRequest();   }    makeRemoteRequest = () => {     const {page, seed} = this.state;     const url = `https://randomuser.me/api/?seed=${seed}&page=${page}&results=20`;     this.setState({loading: true});     fetch(url)       .then(res => res.json())       .then(res => {         this.setState({           data: page === 1 ? res.results : [...this.state.data, ...res.results],           error: res.error || null,           loading: false,           refreshing: false         });       })       .catch(error => {         this.setState({error, loading: false});       });   };    onPressAction = (rowItem) => {     console.log('ListItem was selected');     console.dir(rowItem);     this.setState({       selectedItem: rowItem.id.value     });   }    renderRow = (item) => {     const isSelectedUser = this.state.selectedItem === item.id.value;     console.log(`Rendered item - ${item.id.value} for ${isSelectedUser}`);     const viewStyle = isSelectedUser ? styles.selectedButton : styles.normalButton;     return(         <TouchableOpacity style={viewStyle} onPress={() => this.onPressAction(item)} underlayColor='#dddddd'>           <View style={styles.listItemContainer}>             <View>               <Image source={{ uri: item.picture.large}} style={styles.photo} />             </View>             <View style={{flexDirection: 'column'}}>               <View style={{flexDirection: 'row', alignItems: 'flex-start',}}>                 {isSelectedUser ?                   <Text style={styles.selectedText}>{item.name.first} {item.name.last}</Text>                   : <Text style={styles.text}>{item.name.first} {item.name.last}</Text>                 }               </View>               <View style={{flexDirection: 'row', alignItems: 'flex-start',}}>                 <Text style={styles.text}>{item.email}</Text>               </View>             </View>           </View>         </TouchableOpacity>     );   }    render() {     return(       <FlatList style={styles.container}         data={this.state.data}         renderItem={({ item }) => (           this.renderRow(item)         )}       />     );   } }  const styles = StyleSheet.create({   container: {     flex: 1,     marginTop: 50,   },   selectedButton: {     backgroundColor: 'lightgray',   },   normalButton: {     backgroundColor: 'white',   },   listItemContainer: {     flex: 1,     padding: 12,     flexDirection: 'row',     alignItems: 'flex-start',   },   text: {     marginLeft: 12,     fontSize: 16,   },   selectedText: {     marginLeft: 12,     fontSize: 20,   },   photo: {     height: 40,     width: 40,     borderRadius: 20,   }, }); 

When user taps on an item in the list, "onPress" method is invoked with the information on selected item. But the next step of highlight item in Flatlist does not happen. 'UnderlayColor' is of no help either.

Any help/advice will be much appreciated.

like image 685
Krishnan Sriram Avatar asked Oct 11 '17 10:10

Krishnan Sriram


People also ask

How do I get an index from FlatList?

To get the index of the currently visible item in a React Native flat list, we can set the onViewableItemsChange prop to a function that gets the current visible items. to define the onViewableItemsChanged function that gets the viewableItems property.

What is keyExtractor in FlatList?

keyExtractor ​ (item: object, index: number) => string; Used to extract a unique key for a given item at the specified index. Key is used for caching and as the react key to track item re-ordering. The default extractor checks item. key , then item.id , and then falls back to using the index, like React does.


1 Answers

You can do something like:

  1. For the renderItem, use something like a TouchableOpacity with an onPress event passing the index or id of the renderedItem;

  2. Function to add the selected item to a state:

    handleSelection = (id) => {    var selectedId = this.state.selectedId     if(selectedId === id)      this.setState({selectedItem: null})    else       this.setState({selectedItem: id}) }  handleSelectionMultiple = (id) => {    var selectedIds = [...this.state.selectedIds] // clone state     if(selectedIds.includes(id))      selectedIds = selectedIds.filter(_id => _id !== id)    else       selectedIds.push(id)     this.setState({selectedIds}) } 
  3. FlatList:

    <FlatList   data={data}   extraData={     this.state.selectedId     // for single item     this.state.selectedIds    // for multiple items   }   renderItem={(item) =>       <TouchableOpacity          // for single item        onPress={() => this.handleSelection(item.id)}        style={item.id === this.state.selectedId ? styles.selected : null}          // for multiple items        onPress={() => this.handleSelectionMultiple(item.id)}        style={this.state.selectedIds.includes(item.id) ? styles.selected : null}       >         <Text>{item.name}</Text>      </TouchableOpacity>   } 

    />

  4. Make a style for the selected item and that's it!

like image 130
Maicon Gilton Avatar answered Sep 19 '22 08:09

Maicon Gilton