React-native FlatList道具改变时不重排行
问题描述:
我遇到了新的FlatList组件的问题。具体来说,它不会重新渲染它的行,尽管该行依赖于更改的道具。React-native FlatList道具改变时不重排行
的FlatList文档说:
这是一个PureComponent这意味着它不会重新渲染,如果 道具仍然浅海相等。确保renderItem 函数依赖的所有东西都作为不是===的更新后的道具传递,否则您的UI可能无法更新更改。这包括数据 prop和父组件状态。
问题
不过,看到我改变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}
/>
THE CODE
我的代码的结构是这样的:我有与所有的逻辑和状态的容器组件,其中包含一个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}
/>
CustomList:
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>
);
}
}
(数据来自继电器)
最后行:
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: '',
},
...
};
答
这里的问题在于该
- 你是变异的事实中现有的状态片,而不是创建变异副本
_onCategoryChosen = category => {
var oldReportCopy = this.state.report; // This does not create a copy!
oldReportCopy.selectedCategory = category;
this.setState(Object.assign({}, this.state, { report: oldReportCopy }));
};
这应该是
_onCategoryChosen = category => {
var oldReportCopy = Object.assign({}, this.state.report);
oldReportCopy.selectedCategory = category;
// setState handles partial updates just fine, no need to create a copy
this.setState({ report: oldReportCopy });
};
-
FlatList的道具保持不变,您的
_renderRow
功能可以依赖于selectedCategory
确实会改变的prop(如果不是第一个错误),但FlatList组件不知道这个。要解决此问题,请使用extraData
支柱。<FlatList data={this.props.items.categories.edges} renderItem={this._renderRow} horizontal={true} keyExtractor={(item, index) => item.node.id} extraData={this.props.selectedCategory} />
非常感谢,这完美地工作。回想起来,extraData prop是使用FlatLists时非常重要且可能经常使用的工具 – jhm