我在使用新的FlatList组件时遇到了一个问题。特别是,它不能重新呈现它的行,即使行依赖于更改。
平面列表文档指出:
这是一个PureComponent,这意味着如果属性保持shallow- equal,它将不会重新呈现。请确保renderItem函数所依赖的所有内容都作为属性传递,该属性在更新后不为===,否则UI可能不会根据更改进行更新。这包括数据属性和父组件状态。
问题
然而,看到我改变了selectedCategory项的ID--应该指示行是否被“选中”的属性--我相信这些属性应该重新呈现。
我检查了列表和行组件的'componentWillReceiveProps'方法,列表接收更新的情况良好,但行的生命周期方法从未被调用。
如果我在列表组件中包含一个随机的、无用的布尔状态值,并在属性更新时来回切换它,它就可以工作--但我不知道为什么?
state = { updated: false };
componentWillReceiveProps(nextProps) {
this.setState(oldstate => ({
updated: !oldstate.updated,
}));
}
<FlatList
data={this.props.items.allAnimalCategories.edges}
renderItem={this._renderRow}
horizontal={true}
keyExtractor={(item, index) => item.node.id}
randomUpdateProp={this.state.updated}
/>
法典
我的代码结构如下:我有一个包含所有逻辑和状态的容器组件,其中包含一个FlatList组件(表示型,无状态),该组件也包含一个定制的表示型行。
Container
Custom list component that includes the FlatList component
(presentational, stateless) and the renderRow method
Custom row (presentational, stateless)
该容器包括以下组件:
<CustomList
items={this.props.viewer}
onCategoryChosen={this._onCategoryChosen}
selectedCategory={this.state.report.selectedCategory}
/>
自定义列表:
class CustomList extends Component {
_renderRow = ({ item }) => {
return (
<CustomListRow
item={item.node}
selectedCategory={this.props.selectedCategory}
onPressItem={this.props.onCategoryChosen}
/>
);
};
render() {
return (
<View style={_styles.container}>
<FlatList
data={this.props.items.categories.edges}
renderItem={this._renderRow}
horizontal={true}
keyExtractor={(item, index) => item.node.id}
randomUpdateProp={this.state.updated}
/>
</View>
);
}
}
(data来自中继)
最后一行:
render() {
const idsMatch = this.props.selectedCategory.id == this.props.item.id;
return (
<TouchableHighlight onPress={this._onItemPressed}>
<View style={_styles.root}>
<View style={[
_styles.container,
{ backgroundColor: this._getBackgroundColor() },
]}>
{idsMatch &&
<Image
style={_styles.icon}
source={require('./../../res/img/asd.png')}
/>}
{!idsMatch &&
<Image
style={_styles.icon}
source={require('./../../res/img/dsa.png')}
/>}
<Text style={_styles.text}>
{capitalizeFirstLetter(this.props.item.name)}
</Text>
</View>
<View style={_styles.bottomView}>
<View style={_styles.greyLine} />
</View>
</View>
</TouchableHighlight>
);
}
该行并不那么有趣,但我将其包括在内是为了表明它完全是无状态的,并且依赖于它的父对象。
状态更新如下:
_onCategoryChosen = category => {
var oldReportCopy = this.state.report;
oldReportCopy.selectedCategory = category;
this.setState(Object.assign({}, this.state, { report: oldReportCopy }));
};
状态如下所示:
state = {
...
report: defaultStateReport,
};
const defaultStateReport = {
selectedCategory: {
id: 'some-long-od',
name: '',
},
...
};
9条答案
按热度按时间f45qwnt81#
这里的问题在于
1.您正在变更现有的状态切片,而不是创建变更副本
这应该是
_renderRow
函数可能依赖于selectedCategory
prop,但它确实发生了变化(如果不是第一个错误),但FlatList组件并不知道这一点。要解决此问题,请使用extraData
prop。bwntbbo32#
简单地说,你可以像这样把props传递给flat list组件中的extraData来解决这个问题。
ufj5ltwl3#
在我的例子中,我只是在使用
keyExtractor
时犯了一个简单的错误我变了
至
在过滤列表后,我看到了一个奇怪的效果,过滤后的组件的 prop 被渲染,而不是新组件的 prop ,我相信这是因为我使用了数组的索引,而不是与列表中的项目相关联的唯一键。
szqfcxe24#
我同意Nimelrian的观点。另外,如果你的状态是一个数组,你可以通过以下操作从该状态创建一个数组对象:
然后使用.push()方法向其中添加新对象,如下所示:
然后你可以把这个新的数组对象设置回状态:
kdfy810k5#
也许其他人不会这样做,但我意识到只有当FlatList呈现的项目数组为空时我才会遇到麻烦。在我的情况下,我只需要根本不呈现FlatList,而是在它的位置呈现一个不同的视图,这当然解决了我的“不重新呈现”问题。
mrphzbgm6#
看第4行
ki1q1bka7#
这对我没用
这对我很有效
cbjzeqam8#
在react钩子中,你可以这样做:
fivyi3re9#
这可能是有用的
FlatList
代码