我正在尝试制作过滤复选框列表选项,以过滤要在Feed上显示的新闻。我的应用程序尚未从数据库获取信息,因此我基本上是手动创建测试方法。
我拥有的变量是主题(这是一个州道具),而feedNews,主题是一个数组,其中包含用户希望在Feed中看到的主题,而feedNews是存在于其中的所有新闻组件。进料。
e.g。主题
this.state = {
topics: ['News-1','News-2','News-3']
}
e.g。 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:如果每个主题只有一条新闻,那就没问题了。只有当每个主题有多个新闻
时才会起作用更新
我不确定这是不是问题,但是如果问题是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),
我的过滤器Feed功能也已更改,以适应新的思维方式
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中的新闻有他们的图片,用户只有过滤的反馈
如果我想用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上运行
再次,抱歉在没有提供所有信息的情况下浪费你的时间
答案 0 :(得分:0)
如果我没有弄错,setState不会立即更新状态。所以为了防止这种情况,我建议你在回调上调用函数,如下所示:
this.setState({
value: !this.state.value,
}, ()=> {
this.action(this.name, this.state.value);
});
这有意义吗?