我整理了一个简单的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',}}> <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',text: { marginLeft: 12,fontSize: 16,selectedText: { marginLeft: 12,fontSize: 20,photo: { height: 40,width: 40,borderRadius: 20,});
当用户点击列表中的项目时,将使用所选项目的信息调用“onPress”方法.但是Flatlist中突出显示项目的下一步不会发生. ‘UnderlayColor’也没有任何帮助.
任何帮助/建议将不胜感激.
使用/ check for rowItem.id.value代替this.state.selectedItem和设置,我建议使用带有键:值对的Map对象,如RN FlatList文档示例中所示:
https://facebook.github.io/react-native/docs/flatlist.html.查看js地图文档:
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 onPress={this.props.onPressItem}> ... </TouchableOpacity> ) } }