簡體   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