我有一个FlatList
和一个从Redux 提取的data
道具
render() {
return (
<View>
<FlatList
data={this.props.arrayOfPlacesFromRedux}
renderItem={({item}) => {.......
每当我将更改发送到arrayOfPlacesFromRedux
(即添加或删除子项(时,FlatList
都会重新发送除非我从数组中删除所有子项(即使长度为零(
当arrayOfPlacesFromRedux
从正长度变为零长度时,FlatList
不会重新应答。。。。。然而,对数组的所有其他类型的更改确实会导致FlatList
重新发送
更新02/27下面是我用来更新ReduxarrayOfPlacesFromRedux
的reducer
const reducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_PLACES_ARRAY:
return {...state, arrayOfPlaces: action.payload};
default:
return state;
}
};
在上述情况下,当FlatList没有重新发送时。。。。。action.payload
是空数组
问题缺少一些重要的代码。React和Redux都需要数组引用来更改,这意味着对于要在状态更改时重新渲染的组件,数组引用需要更改。
现场演示https://snack.expo.dev/RrFFxfeWY
以下是最有趣的部分:
如果您有以下基本组件:
const MyList = () => {
const [data, setData] = React.useState([
'#FF0000',
'#FF8000',
'#FFFF00',
]);
return (
<>
<Text>List poping is not working</Text>
<FlatList
data={data}
renderItem={({ item }) => (
<Pressable
onPress={() => {
data.pop(); // Does not work because we are not changing it's ref
}}
style={{ backgroundColor: item, padding: 8 }}>
<Text>{item}</Text>
</Pressable>
)}
/>
</>
);
};
data
需要有一个新的数组引用,如下所示。data2.filter(..)
将返回一个新数组,我们不会更改data2的基本值,只是创建一个少了一项的新数组。
const MyList = () => {
const [data2, setData2] = React.useState([
'#00FFFF',
'#0080FF',
'#0000FF',
]);
return (
<>
<Text>List WORKING!</Text>
<FlatList
data={data2}
renderItem={({ item }) => (
<Pressable
onPress={() => {
setData2(data2.filter(dataItem => dataItem !== item)) // works
//setData2([]); // Also works
}}
style={{ backgroundColor: item, padding: 8 }}>
<Text>{item}</Text>
</Pressable>
)}
/>
</>
);
};
像Immer.js这样的库简化了对状态的操作以改变对象,Immer将为您创建一个新的引用。
哦,没有浪费每个人时间的新手错误!!我正在执行shouldComponentUpdate
方法,该方法将停止平面列表渲染:(感谢所有的答案
您可能需要使用ListEmptyComponent
,这是FlatList src附带的一个道具。
老实说,我不知道为什么在更新状态时它不重新渲染,也不知道为什么他们在数组为空时添加了一个特定的函数/道具来渲染,但从文档中可以清楚地看出,这正是所需要的。
你可以这样做:
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
--> ListEmptyComponent={() => <MyComponent />}
/>
</SafeAreaView>