当数据属性更改为空数组时,本机 FlatList 不会重新呈现
React native FlatList not rerendering when data prop changes to empty array
我有一个 FlatList
和一个从 Redux
拉取的 data
道具
render() {
return (
<View>
<FlatList
data={this.props.arrayOfPlacesFromRedux}
renderItem={({item}) => {.......
每当我发送对 arrayOfPlacesFromRedux
的更改(即添加或删除子项)时,FlatList
重新呈现....UNLESS 我从中删除所有子项数组(即使长度为零)。
当 arrayOfPlacesFromRedux
从正长度变为零长度时,FlatList
不会重新呈现......但是所有其他类型的更改数组确实会导致 FlatList
重新渲染
更新 02/27
下面是我用来更新 Redux 的 reducer arrayOfPlacesFromRedux
const reducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_PLACES_ARRAY:
return {...state, arrayOfPlaces: action.payload};
default:
return state;
}
};
在上面提到的 FlatList 不重新渲染的情况下.....action.payload
是一个空数组
可能需要用到ListEmptyComponent
,这是FlatList自带的prop,src.
老实说,我不确定为什么当你更新你的状态时它没有 re-render,或者为什么他们添加了一个特定的 function/prop 来在数组为空时呈现,但是从文档说明这是需要的。
你可以这样做:
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
--> ListEmptyComponent={() => <MyComponent />}
/>
</SafeAreaView>
问题缺少一些重要的代码。
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(..)
将 return 一个新数组,我们不会更改 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 将为您创建一个新的引用。
哦,没有浪费大家时间的菜鸟错误!!
我正在实施停止 Flatlist 渲染的 shouldComponentUpdate
方法 :(
感谢大家的回答
我有一个 FlatList
和一个从 Redux
data
道具
render() {
return (
<View>
<FlatList
data={this.props.arrayOfPlacesFromRedux}
renderItem={({item}) => {.......
每当我发送对 arrayOfPlacesFromRedux
的更改(即添加或删除子项)时,FlatList
重新呈现....UNLESS 我从中删除所有子项数组(即使长度为零)。
当 arrayOfPlacesFromRedux
从正长度变为零长度时,FlatList
不会重新呈现......但是所有其他类型的更改数组确实会导致 FlatList
重新渲染
更新 02/27
下面是我用来更新 Redux 的 reducer arrayOfPlacesFromRedux
const reducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_PLACES_ARRAY:
return {...state, arrayOfPlaces: action.payload};
default:
return state;
}
};
在上面提到的 FlatList 不重新渲染的情况下.....action.payload
是一个空数组
可能需要用到ListEmptyComponent
,这是FlatList自带的prop,src.
老实说,我不确定为什么当你更新你的状态时它没有 re-render,或者为什么他们添加了一个特定的 function/prop 来在数组为空时呈现,但是从文档说明这是需要的。
你可以这样做:
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
--> ListEmptyComponent={() => <MyComponent />}
/>
</SafeAreaView>
问题缺少一些重要的代码。 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(..)
将 return 一个新数组,我们不会更改 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 将为您创建一个新的引用。
哦,没有浪费大家时间的菜鸟错误!!
我正在实施停止 Flatlist 渲染的 shouldComponentUpdate
方法 :(
感谢大家的回答