jhm*_*jhm 28 react-native react-native-listview
我遇到了新的FlatList组件的问题.具体来说,它不会重新渲染它的行,即使该行依赖于变化的道具.
FlatList文档说:
这是一个PureComponent,这意味着如果道具保持浅层相等,它将不会重新渲染.确保您的renderItem函数所依赖的所有内容在更新后作为非_ =的prop传递,否则您的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}
/>
Run Code Online (Sandbox Code Playgroud)
代码
我的代码的结构是这样的:我有一个包含所有逻辑和状态的容器组件,它包含一个FlatList组件(表示,无状态),它还包含一个自定义的表示行.
Container
Custom list component that includes the FlatList component
(presentational, stateless) and the renderRow method
Custom row (presentational, stateless)
Run Code Online (Sandbox Code Playgroud)
容器包含此组件:
<CustomList
items={this.props.viewer}
onCategoryChosen={this._onCategoryChosen}
selectedCategory={this.state.report.selectedCategory}
/>
Run Code Online (Sandbox Code Playgroud)
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>
);
}
Run Code Online (Sandbox Code Playgroud)
}
(数据来自Relay)
最后一行:
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>
);
}
Run Code Online (Sandbox Code Playgroud)
这行不是那么有趣,但我把它包括在内,表明它完全是无国籍的,并且依赖于它的父母道具.
状态更新如下:
_onCategoryChosen = category => {
var oldReportCopy = this.state.report;
oldReportCopy.selectedCategory = category;
this.setState(Object.assign({}, this.state, { report: oldReportCopy }));
};
Run Code Online (Sandbox Code Playgroud)
州看起来像这样:
state = {
...
report: defaultStateReport,
};
const defaultStateReport = {
selectedCategory: {
id: 'some-long-od',
name: '',
},
...
};
Run Code Online (Sandbox Code Playgroud)
Nim*_*ian 68
这里的问题在于:
_onCategoryChosen = category => {
var oldReportCopy = this.state.report; // This does not create a copy!
oldReportCopy.selectedCategory = category;
this.setState(Object.assign({}, this.state, { report: oldReportCopy }));
};
Run Code Online (Sandbox Code Playgroud)
这应该是
_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 });
};
Run Code Online (Sandbox Code Playgroud)
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}
/>
Run Code Online (Sandbox Code Playgroud)Jan*_*ara 37
只要你能解决这个问题,通过道具来而额外在平面列表这样的成分,
<FlatList
data={this.props.data}
extraData={this.props}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
Run Code Online (Sandbox Code Playgroud)
小智 5
我同意尼梅尔里安的观点。此外,如果您的状态是一个数组,您可以通过执行以下操作从该状态创建一个数组对象:
var oldReportCopy = Object.assign([], this.state.report);
Run Code Online (Sandbox Code Playgroud)
然后使用 .push() 方法将新对象添加到它,如下所示:
oldReportCopy.push(selectedCategory);
Run Code Online (Sandbox Code Playgroud)
然后,您可以将这个新的数组对象设置回状态:
this.setState({ report: oldReportCopy });
Run Code Online (Sandbox Code Playgroud)
就我而言,我在使用时犯了一个简单的错误 keyExtractor
我变了
keyExtractor={(item, index) => index.toString()}
Run Code Online (Sandbox Code Playgroud)
到
keyExtractor={(item, index) => item.key}
Run Code Online (Sandbox Code Playgroud)
在过滤我的列表后,我看到了一些奇怪的效果,其中过滤掉的组件的 props 被渲染来代替新组件的 props,我的预感是因为我使用的是数组的索引而不是唯一的键,我只是传递了旧的 props 到新的组件,即使基础组件实际上在改变。
归档时间: |
|
查看次数: |
27089 次 |
最近记录: |