簡體   English   中英

在React Native上過濾組件

[英]Filtering Components on React Native

我正在嘗試制作一個過濾復選框列表選項,以過濾掉要在Feed上顯示的新聞。 我的應用程序還沒有從數據庫獲取信息,所以我基本上是手工創建測試方法。

我擁有的變量是主題(這是一個州道具),而feedNews,主題是一個數組,其中包含用戶希望在Feed中看到的主題,而feedNews是存在於Feed中顯示的所有新聞組件。

例如主題

this.state = {
  topics: ['News-1','News-2','News-3']
}

例如feedNews的組件

const feedNews = [
    {name:'News-1', comp: <FeedNews key={101} name="News-1" />},
    {name:'News-2', comp: <FeedNews key={102} name="News-2" />},
    {name:'News-3', comp: <FeedNews key={103} name="News-3" />},
    {name:'News-1', comp: <FeedNews key={104} name="News-1" />},
    {name:'News-3', comp: <FeedNews key={105} name="News-3" />}
]

注意:每個組件上的鍵僅用於測試

基本上我在我的類的渲染上有一個函數,它返回過濾的組件數組:

filterFeedNews(){
    let topics = this.state.topics;
    return feedNews.filter((item) => {
        return topics.indexOf(item.name)!==-1;
    }).map(item => item.comp);
}

現在這個函數每次我第一次打開應用程序時都能正常工作,但是如果我實際上用我的過濾器選項(復選框列表)更改了主題數組,有時會有選項消失而且它們不是我選擇的選項。 順便說一句,更新過濾功能是這樣的:

updateFilter(newsName, value){
    let newNewsTopics = this.state.topics;
    if(value){
        newNewsTopics.push(newsName);
    }else{
        newNewsTopics.splice(newNewsTopics.indexOf(newsName),1);
    }
    this.props.dispatch(setNewsFilter(newNewsTopics));
    this.setState({
        newsTopics: newNewsTopics,
    });
}

這個函數被每個復選框中的bind作為動作調用(因為道具的名稱)

onClick(){
    this.action(this.name, !this.state.value);
    this.setState({
        value: !this.state.value,
    });
}

我的問題是,我在這些函數上做錯了什么,或者在本地反應中發生這種情況是“正常的”

PS:如果每個主題只有一個新聞,那就沒問題了。 僅當每個主題有多個新聞時,這才起作用

UPDATE

我不確定這是否是問題,但如果問題是ScrollView而不是ListView進行過濾和渲染

render(){
        return (
            <View style={styles.root}>
                <Toolbar home={true} options={true} title='Feed' actionOptions={this.optionsAction.bind(this)}/>
                <View style={styles.flexContainer}>
                    <ScrollView style={styles.flexContainer}>
                        {this.filterFeedNews()}
                    </ScrollView>
                </View>
                <View style={styles.spacing} />
                {this.options()}
            </View>
        );
    }

所以基本上主要是甚至不過濾,問題更多的是組件的渲染。 在同事的幫助下,我不得不改變我上面發布的結構。 改變了什么:

const feedNews = [
    {name:'News-1', ...otherProps},
    {name:'News-2', ...otherProps},
    {name:'News-3', ...otherProps},
    {name:'News-1', ...otherProps},
    {name:'News-3', ...otherProps}
];

在我的州添加了一個dataSource

dataSource: ds.cloneWithRows(feedNews),

我的過濾器輸入功能也發生了變化,以適應新的思維方式

filterFeedNews(){
        let topics = this.state.newsTopics;
        let feed = feedNews.filter((item) => {
            return topics.includes(item.name);
        });
        const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
        this.setState({dataSource: ds.cloneWithRows(feed)});
    }

我的更新過濾器操作也必須更改

updateFilter(newsName, value){
        let newNewsTopics = this.state.topics;
        if(value){
            newNewsTopics.push(newsName);
        }else{
            newNewsTopics.splice(newNewsTopics.indexOf(newsName), 1);
        }
        this.props.dispatch(setNewsFilter(newNewsTopics));
        this.setState({
            newsTopics: newNewsTopics,
        }, () => this.filterFeedNews());
    }

而我的渲染而不是ScrollView它現在有一個ListView

<ListView
        style={styles.flexContainer}
        dataSource={this.state.dataSource}
        removeClippedSubviews={false}
        renderRow={(rowData, sectionID, rowID) => this.renderRow(rowData, sectionID, rowID)}
        enableEmptySections={true}
/>

親:它沒有我以前的方法遇到的問題

Con:我每次更新組件時使用的LayoutAnimation都不能與ListView一起使用,因此如果Feed中的新聞有他們的圖片,用戶只有過濾的反饋

解決方案維護ScrollView

如果我想用Scroll View保留我的初始方法,我的解決方案基本上就是這個

updateFilter(newsName, value){
     let newNewsTopics = this.state.topics;
     if(value){
         newNewsTopics.push(newsName);
     }else{
         newNewsTopics.splice(newNewsTopics.indexOf(newsName), 1);
     }
     this.props.dispatch(setNewsFilter(newNewsTopics));
     this.setState({
        newsTopics: newNewsTopics,
    });
}

filterFeedNews(){
    let topics = this.state.topics;
    let i = 0;
    return feedNews.filter((item) => {
        return topics.includes(item.name);
    }).map((item) => {
        return (<FeedNews key={++i} name={item.name}/>);
    });
}

this.state.topics維護結構(一個字符串數組),而feedNews基本上變成一個對象數組,就像上面的例子中對於前面的解決方案一樣 ,然后用函數filterFeedNews轉換為使用filter和map o“convert “進入一系列組件。 在某種程度上,結果與ListView完全相同,原始動畫不是“工作”,但這是因為實現的完成方式。

動畫解決方案

我遇到的問題導致我上面討論的所有問題實際上都是因為LayoutAnimation,每當我“刪除”帶有過濾選項的新聞源時,布局動畫最終刪除的內容超過了特定類別的新聞源。

我為此道歉,因為我認為LayoutAnimation不是問題而且我沒有發布那部分代碼。

基本上這個刪除問題不會發生,現在的解決方案是:

LayoutAnimation.configureNext({
        duration: 300,
        create: {
            type: LayoutAnimation.Types.easeInEaseOut,
            property: LayoutAnimation.Properties.opacity,
        },
        update: { type: LayoutAnimation.Types.easeInEaseOut },
    });

如果你問為什么我沒有刪除,那是因為在LayouAnimation中刪除在Android上運行不正常,只在iOS上運行

再次,抱歉在沒有提供所有信息的情況下浪費你的時間

如果我沒有弄錯,setState不會立即更新狀態。 所以為了防止這種情況,我建議你在回調上調用函數,如下所示:

this.setState({
    value: !this.state.value,
}, ()=> {
    this.action(this.name, this.state.value);
});

這有道理嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM