У меня возникла проблема с новым компонентом FlatList. В частности, он не перезаписывает строки, даже если реквизит зависит от изменений строки.
Документы FlatList говорят, что:
Это PureComponent, что означает, что он не будет повторно отображать, если реквизит остается неглубоким. Убедитесь, что все ваше renderItem функция зависит от передается в качестве опоры, которая не является === после обновлений, в противном случае ваш пользовательский интерфейс может не обновляться при внесении изменений. Сюда входят данные prop и родительского компонента.
ВОПРОС
Однако, видя, как я изменяю идентификатор выбранного объекта категории - оповещение, которое должно указывать, выбрана ли строка или нет, я считаю, что реквизит должен быть повторно. Я ошибаюсь?
Я проверил методы 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}
/>
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: '',
},
...
};