2017-10-11 144 views
2

我將一個簡單的React本機應用程序放在一起,以從遠程服務獲取數據,並將其加載到FlatList中。當用戶點擊某個項目時,應突出顯示並保留選擇內容。我相信這樣的小事不應該很難。我不知道我錯過了什麼。突出顯示React-Native FlatList中的選定項目

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, 
    }, 
}); 

當用戶點擊在列表中的項目,「onPress」方法被調用與選擇的項目的信息。但Flatlist中突出顯示項目的下一步不會發生。 'UnderlayColor'也沒有幫助。

任何幫助/建議將不勝感激。

+1

您還需要修改您的數據(狀態),在'onPressAction' FUNC代替'和'this.setState setState'({將selectedItem :rowItem.id.value,data:{... this.state.data}});'但這不是建議的方法。 –

+0

我試過了。沒有幫助 –

回答

0

代替的this.state.selectedItem並與設置/檢查一個rowItem.id.value,我建議使用與密鑰的地圖對象:值對如圖所示的RN FlatList文檔例如:https://facebook.github.io/react-native/docs/flatlist.html。請看看js Map文檔:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

@ j.I-V推薦的extraData prop將確保在選擇this.state.selected時發生更改。

你onPressAction顯然會改變取決於以下,如果要限制選擇的數目在任何特定時間或不允許用戶切換選擇從例子有點等

另外,儘管沒有任何必要意味着,我喜歡爲renderItem組件使用另一個類或純組件;最終看起來像下面這樣:

export default class BasicFlatList extends Component { 
 
    state = { 
 
    otherStateStuff: ..., 
 
    selected: (new Map(): Map<string, boolean>) //iterable object with string:boolean key:value pairs 
 
    } 
 

 
    onPressAction = (key: string) => { 
 
    this.setState((state) => { 
 
     //create new Map object, maintaining state immutability 
 
     const selected = new Map(state.selected); 
 
     //remove key if selected, add key if not selected 
 
     this.state.selected.has(key) ? selected.delete(key, !selected.get(key)) : selected.set(key, !selected.get(key)); 
 
     return {selected}; 
 
    }); 
 
    } 
 

 
    renderRow = (item) => { 
 
    return (
 
     <RowItem 
 
      {...otherProps} 
 
      item={item} 
 
      onPressItem={this.onPressAction} 
 
      selected={!!this.state.selected.get(item.key)} /> 
 
    ); 
 
    } 
 

 
    render() { 
 
    return(
 
     <FlatList style={styles.container} 
 
     data={this.state.data} 
 
     renderItem={({ item }) => (
 
      this.renderRow(item) 
 
     )} 
 
     extraData={this.state} 
 
     /> 
 
    ); 
 
    } 
 
} 
 

 

 
class RowItem extends Component { 
 
    render(){ 
 
    //render styles and components conditionally using this.props.selected ? _ : _ 
 
    
 
    return (
 
     <TouchableOpacity> 
 
     ... 
 
     </TouchableOpacity> 
 
    ) 
 
    } 
 
}

0

您應該根據您的選擇

這裏傳遞一個而額外道具你FlatList,這樣它會重新呈現你的項目:

<FlatList style={styles.container} 
    data={this.state.data} 
    extraData={this.state.selectedItem} 
    renderItem={({ item }) => (
     this.renderRow(item) 
    )} 
/> 

來源:https://facebook.github.io/react-native/releases/next/docs/flatlist.html

確保一切你的renderItem函數依賴於作爲一個道具(例如extraData)傳遞,不是更新後的===,否則你的UI可能不會在更新時更新

相關問題