简体   繁体   English

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

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

I'm creating a list of collapsible using the react native flatlist component. 我正在使用react native flatlist组件创建可折叠列表。

I'm using ref attribute to get the item clicked. 我正在使用ref属性来单击该项目。

But when i try to access the ref from the click event, it doesn't take effect on the clicked item but on the last item in the flatlist. 但是,当我尝试从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)}
        />
    )
}

} }

I also tried placing using the index of the items, but couldn't make it work. 我还尝试使用项目的索引进行放置,但无法使其正常工作。

Any way around this? 可以解决吗? I think the ref are overwritten by the next one when the items are rendering. 我认为在渲染项目时,下一个参考将覆盖该参考。

You are right about your assumption. 您的假设是正确的。 Ref is overwriting with the next item so ref is the last item's ref. 参考被下一项覆盖,因此参考是最后一项的参考。 You can use something like below to set each items ref separately. 您可以使用以下类似的方法分别设置每个项目的引用。

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

Of course this solution assumes you have a unique id or sort in your item data. 当然,此解决方案假定您在项目数据中具有唯一的ID或排序。

To paraphrase the React Native docs, direct manipulation (ie refs) should be used sparingly; 为了解释React Native文档,应谨慎使用直接操作(即refs)。 unless you need it for some other reason I'm unaware of, refs aren't necessary in this case. 除非您出于我不知道的其他原因而需要它,否则在这种情况下不需要引用。 Typically, the best way to keep track of selected items in a FlatList is by utilizing the keyExtractor and extraData props in conjunction with a Javascript Map object in state. 通常,跟踪FlatList中选定项目的最佳方法是将keyExtractorextraData与处于状态的Javascript Map对象结合使用。

The way React is able to keep track of items being added/removed/modified is by using a unique key prop for each item (preferably an id, or if necessary indexes work if the list order will not change). React能够跟踪添加/删除/修改的项目的方式是为每个项目使用唯一的key道具(最好是id,或者如果列表顺序不会改变,则必要时索引也可以工作)。 In a FlatList, this is handled "automagically" if you will using the keyExtractor prop. 在FlatList中,如果您将使用keyExtractor则将“自动”处理该keyExtractor To keep track of the selected item, we can add/remove items from our Map object whenever we click on one. 为了跟踪选定的项目,每当单击一个项目时,就可以从Map对象中添加/删除项目。 Map is a type of object like an array that holds key-value pairs. Map是一种对象类型,例如包含键值对的数组。 We'll use this in state to store a key item.id and a boolean value true for each item that is selected. 我们将使用此状态存储一个关键item.id和一个布尔值true用于选择的每个项目。

So, we end up with something like this: 因此,我们最终得到这样的结果:

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

You'll have to play around with the styles.itemBodySelected to make it look how you want. 您必须使用styles.itemBodySelected使其看起来像您想要的。 Note that the separate functional component <ExpandableItem /> for the renderItem isn't required, just how I prefer to structure my code. 请注意,不需要renderItem的单独功能组件<ExpandableItem /> ,而是我更喜欢结构代码的方式。

Helpful links: 有用的网址:

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

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

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

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

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