繁体   English   中英

在Flatlist项目中反应Native ref。 仅返回最后一个项目

[英]React Native ref in Flatlist items. Returning for last item alone

我正在使用react native flatlist组件创建可折叠列表。

我正在使用ref属性来单击该项目。

但是,当我尝试从click事件访问ref时,它不会对单击的项目起作用,而是对平面列表中的最后一个项目起作用。

export default class Update extends Component {

renderItems (data, index) {
    return (
        <TouchableNativeFeedback
            onPress={() => this.expandView()}
        >
            <View style={[styles.itemWrapperExpandable]}>
                <View style={styles.itemHeader}>
                    <View style={styles.itemAvatar}>
                        <Image source={require('../images/logo.png')} style={styles.avatar}></Image>
                    </View>
                    <View style={styles.itemContent}>
                        <Text style={[styles.itemTitle, styles.black]}>{data.name}</Text>
                        <Text style={[styles.rating, styles.grey]}>
                            {data.rating}<Icon name="star"></Icon>
                        </Text>
                        <Text style={[styles.content, styles.black]}>{data.description}</Text>
                    </View>
                    <View style={styles.itemBtn}>
                        <Icon name="chevron-down" style={{ color: '#000', fontSize: 22 }}></Icon>
                    </View>
                </View>
                <View ref={(e) => this._expandableView = e } style={[styles.itemBody]}>
                    <Text style={styles.itemBodyText}>
                        some more information about this update will appear here
                        some more information about this update will appear here
                </Text>
                </View>
            </View>
        </TouchableNativeFeedback>
    );
}

expandView () {
    LayoutAnimation.easeInEaseOut();
    if (this._expandableView !== null) {
        if (!this.state.isExpanded) {
            // alert(this.state.isExpanded)
            this._expandableView.setNativeProps({
                style: {height: null, paddingTop: 15, paddingBottom: 15,}
            })
        }
        else {
            this._expandableView.setNativeProps({
                style: {height: 0, paddingTop: 0, paddingBottom: 0,}
            });
        }


        this._expandableView.setState(prevState => ({
            isExpanded: !prevState
        }));
    }
}

render() {
    return (
        <FlatList
            data={this.state.data}
            renderItem={({ item, index }) => this.renderItems(item, index)}
        />
    )
}

}

我还尝试使用项目的索引进行放置,但无法使其正常工作。

可以解决吗? 我认为在渲染项目时,下一个参考将覆盖该参考。

您的假设是正确的。 参考被下一项覆盖,因此参考是最后一项的参考。 您可以使用以下类似的方法分别设置每个项目的引用。

ref={(ref) => this.refs[data.id] = ref}

当然,此解决方案假定您在项目数据中具有唯一的ID或排序。

为了解释React Native文档,应谨慎使用直接操作(即refs)。 除非您出于我不知道的其他原因而需要它,否则在这种情况下不需要引用。 通常,跟踪FlatList中选定项目的最佳方法是将keyExtractorextraData与处于状态的Javascript Map对象结合使用。

React能够跟踪添加/删除/修改的项目的方式是为每个项目使用唯一的key道具(最好是id,或者如果列表顺序不会改变,则必要时索引也可以工作)。 在FlatList中,如果您将使用keyExtractor则将“自动”处理该keyExtractor 为了跟踪选定的项目,每当单击一个项目时,就可以从Map对象中添加/删除项目。 Map是一种对象类型,例如包含键值对的数组。 我们将使用此状态存储一个关键item.id和一个布尔值true用于选择的每个项目。

因此,我们最终得到这样的结果:

 export default class Update extends Component { state = { data: [], selected: (new Map(): Map<string, boolean>) } renderItems = ({ item }) => { // note: the double ! operator is to make sure non boolean values are properly converted to boolean return ( <ExpandableItem item={item} selected={!!this.state.selected.get(item.id)} expandView={() => this.expandView(item)} /> ); } expandView (item) { LayoutAnimation.easeInEaseOut(); this.setState((state) => { const selected = new Map(state.selected); selected.set(item.id, !selected.get(item.id)); return {selected}; }); // the above allows for multiple expanded items at a time; the following will simultaneously close the last item when expanding a new one // this.setState((state) => { // const selected = new Map(); // selected.set(item.id, true); // return {selected}; // }); } render() { return ( <FlatList data={this.state.data} keyExtractor={(item, index) => `${item.id}`} renderItem={this.renderItems} /> ); } } const ExpandableItem = ({ item, selected, expandView }) => { return ( <TouchableNativeFeedback onPress={expandView}> <View style={styles.itemWrapperExpandable}> {/* ...insert other header code */} <View style={[styles.itemBody, selected && styles.itemBodySelected]}> <Text style={styles.itemBodyText}> some more information about this update will appear here </Text> </View> </View> </TouchableNativeFeedback> ); } 

您必须使用styles.itemBodySelected使其看起来像您想要的。 请注意,不需要renderItem的单独功能组件<ExpandableItem /> ,而是我更喜欢结构代码的方式。

有用的网址:

https://facebook.github.io/react-native/docs/flatlist.html

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

https://reactjs.org/docs/lists-and-keys.html#keys

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM