【发布时间】:2017-09-06 22:30:10
【问题描述】:
我正在尝试制作一个过滤复选框列表选项来过滤掉要在提要上显示的新闻。我的应用还没有从数据库中获取信息,所以我基本上是手动创建来测试这些方法。
我拥有的变量是主题(这是一个状态道具),而 feedNews,topics 是一个数组,其中包含用户希望在 feed 中看到的主题,而 feedNews 是存在的所有新闻组件,可以显示在饲料。
例如主题
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,
});
}
这个函数被每个复选框内的绑定调用为动作(因为道具的名称)
onClick(){
this.action(this.name, !this.state.value);
this.setState({
value: !this.state.value,
});
}
我的问题是,我在这些功能上做错了什么,或者在 react-native 中发生这种情况是否“正常”
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: 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}
/>
专业人士:它没有我以前的方法遇到的问题
缺点:我每次更新组件时使用的 LayoutAnimation 不适用于 ListView,因此如果提要中的新闻有他们的图片,用户只有过滤的反馈
维护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 基本上变成了一个对象数组,就像上一个 solution 的例子一样,然后它被转换为函数 filterFeedNews 使用过滤器和映射“转换”为组件数组。 在某种程度上,结果与 ListView 完全一样,原来的动画没有“工作”,但这是因为实现的方式。
动画解决方案
导致上面提到的所有问题的问题实际上是由于 LayoutAnimation,每次我“删除”带有过滤选项的新闻提要时,布局动画最终从特定类别中删除的不仅仅是新闻提要。
对此我深表歉意,因为我认为 LayoutAnimation 不是问题,因此我没有发布那部分代码。
基本不会出现这种删除问题,目前解决办法是这样:
LayoutAnimation.configureNext({
duration: 300,
create: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity,
},
update: { type: LayoutAnimation.Types.easeInEaseOut },
});
如果你问我为什么不删除,那是因为在 LayouAnimation 中删除在 Android 上不能正常工作,只能在 iOS 上工作
再次抱歉,没有提供所有信息就浪费了您的时间
【问题讨论】:
标签: javascript react-native redux flux react-native-router-flux