繁体   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