如何重新渲染平面列表?
How to re-render flatlist?
与 ListView 不同,我们可以更新 this.state.datasource。是否有更新或重新渲染 FlatList 的方法或示例?
我的目标是在用户按下按钮时更新文本值...
renderEntries({ item, index }) {
return(
<TouchableHighlight onPress={()=> this.setState({value: this.state.data[index].value+1})>
<Text>{this.state.data[index].value}</Text>
</TouchableHighlight>
)
}
<FlatList
ref={(ref) => { this.list = ref; }}
keyExtractor={(item) => item.entry.entryId}
data={this.state.data}
renderItem={this.renderEntries.bind(this)}
horizontal={false} />
如果您要有一个按钮,您可以使用 onPress 中的 setState 更新数据。然后 SetState 将重新呈现您的 FlatList。
在 FlatList 组件上使用 extraData
属性。
如文档所述:
By passing extraData={this.state}
to FlatList
we make sure FlatList
will re-render itself when the state.selected
changes. Without setting this prop, FlatList
would not know it needs to re-render any items because it is also a PureComponent
and the prop comparison will not show any changes.
哦,很简单,用extraData
你看到额外数据在幕后工作的方式是 FlatList 或 VirtualisedList 只是通过检查 wether that object has changed正常 onComponentWillReceiveProps
方法。
所以你所要做的就是确保你提供的东西会改变extraData
。
这是我的做法:
我正在使用 immutable.js 所以我所做的就是传递一个 Map(不可变对象),其中包含我想观看的内容。
<FlatList
data={this.state.calendarMonths}
extraData={Map({
foo: this.props.foo,
bar: this.props.bar
})}
renderItem={({ item })=>((
<CustomComponentRow
item={item}
foo={this.props.foo}
bar={this.props.bar}
/>
))}
/>
这样,当 this.props.foo
或 this.props.bar
发生变化时,我们的 CustomComponentRow
也会更新,因为不可变对象将与之前的对象不同。
我已将 FlatList
替换为 SectionList
并且它会在状态更改时正确更新。
<SectionList
keyExtractor={(item) => item.entry.entryId}
sections={section}
renderItem={this.renderEntries.bind(this)}
renderSectionHeader={() => null}
/>
唯一需要记住的是 section
有 diff 结构:
const section = [{
id: 0,
data: this.state.data,
}]
要获得快速简单的解决方案,请尝试:
将额外数据设置为布尔值。
extraData={this.state.refresh}
想要re-render/refresh列表时切换布尔状态的值
this.setState({
refresh: !this.state.refresh
})
对我来说,诀窍是 extraData 并再次深入到项目组件
state = {
uniqueValue: 0
}
<FlatList
keyExtractor={(item, index) => item + index}
data={this.props.photos}
renderItem={this.renderItem}
ItemSeparatorComponent={this.renderSeparator}
/>
renderItem = (item) => {
if(item.item.selected) {
return ( <Button onPress={this.itemPressed.bind(this, item)}>Selected</Button> );
}
return ( <Button onPress={this.itemPressed.bind(this, item)}>Not selected</Button>);
}
itemPressed (item) {
this.props.photos.map((img, i) => {
if(i === item.index) {
if(img['selected') {
delete img.selected;
} else {
img['selected'] = true;
}
this.setState({ uniqueValue: this.state.uniqueValue +1 });
}
}
}
将您的互动更改的变量放在 extraData
你可以发挥创意。
例如,如果您正在处理一个带有复选框的更改列表。
<FlatList
data={this.state.data.items}
extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
renderItem={({item}) => <View>
OK.I 刚刚发现,如果我们想让 FlatList 知道 data prop 之外的数据变化,我们需要将它设置为 extraData,所以我现在这样做:
<FlatList data={...} extraData={this.state} .../>
参考:https://facebook.github.io/react-native/docs/flatlist#extradata
我通过添加 extraData={this.state}
解决了这个问题,请查看下面的代码了解更多详情
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.arr}
extraData={this.state}
renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
/>
</View>
);
}
如果我们想让FlatList知道数据变化prop和state,我们可以构造一个同时引用prop和state的对象并刷新平面列表。
const hasPropOrStateChange = { propKeyToWatch: this.props, ...this.state};
<FlatList data={...} extraData={this.hasPropOrStateChange} .../>
文档:https://facebook.github.io/react-native/docs/flatlist#extradata
经过大量搜索和寻找真正的答案后,我终于得到了我认为最好的答案:
<FlatList
data={this.state.data}
renderItem={this.renderItem}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
ItemSeparatorComponent={this.renderSeparator}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={1}
extraData={this.state.data}
removeClippedSubviews={true}
**keyExtractor={ (item, index) => index }**
/>
.....
我的主要问题是 (KeyExtractor)
我没有像这样使用它。
不工作:keyExtractor={ (item) => item.ID}
在我改成这个之后它就像魅力一样工作
我希望这对某人有所帮助。
只需使用:
onRefresh={true}
在您的 flatList
组件中。
在react-native-flatlist中,它们是一个叫做extraData的属性。将以下行添加到您的平面列表中。
<FlatList
data={data }
style={FlatListstyles}
extraData={this.state}
renderItem={this._renderItem}
/>
在此示例中,要强制重新渲染,只需更改变量 machine
const [selected, setSelected] = useState(machine)
useEffect(() => {
setSelected(machine)
}, [machine])
Flatlist 的 extraData 对我不起作用,我碰巧使用了 redux 的 prop。这听起来与 ED209 的回答中的评论中的问题类似。当我收到道具时,我最终手动调用了 setState。
componentWillReceiveProps(nextProps: StateProps) {
if (this.props.yourProp != null && nextProps.yourProp) {
this.setState({ yourState: processProp(nextProps.yourProp) });
}
}
<FlatList
data={this.state.yourState}
extraData={this.state.yourState}
/>
对于那些使用 > React 17 的人,请使用 getDerivedStateFromProps
这里只是对之前答案的扩展。
要确保两部分,确保您添加了 extraData 并且您的 keyExtractor 是唯一的。如果您的 keyExtractor 是常量,则不会触发重新渲染。
<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
</FlatList>
我正在使用功能组件,因为我正在使用 Flatlist 和 redux 数据。
我正在使用 Redux store 管理所有状态。
这是在 api 调用后更新 Flatlist 数据的解决方案。
我第一次是这样做的:-
const DATA = useSelector((state) => state.address.address);
<FlatList
style = {styles.myAddressList}
data = {DATA}
renderItem = {renderItem}
keyExtractor = {item => item._id}
ListEmptyComponent = {EmptyList}
ItemSeparatorComponent={SeparatorWhite}
extraData = {refresh}
/>
但数据根本没有重新呈现我的 Flatlist 数据。
作为我喜欢的解决方案,如下所示:-
<FlatList
style = {styles.myAddressList}
data = {useSelector((state) => state.address.address)}
renderItem = {renderItem}
keyExtractor = {item => item._id}
ListEmptyComponent = {EmptyList}
ItemSeparatorComponent={SeparatorWhite}
/>
我将 Redux 状态直接传递给 Flatlist 数据源,而不是将其分配给变量。
谢谢。
const [itemSelected, setItemSelected] = setState(null);
....
const FlatListItem = (item) => {
return (
<TouchableOpacity onPress={() => setItemSelected(item.id)}>
<View style={ (itemSelected === item.id) ? style.itemWrapperActive : style.itemWrapper }>
<Text>{ item.label }</Text>
</View>
</TouchableOpacity>
)
}
....
<FlatList
ItemSeparatorComponent={() => <View style={{ width: 20 }} />}
data={ flatListData }
renderItem={ ({item}) => FlatListItem(item) }
keyExtractor={ (item) => item.id }
extraData={ itemSelected }
/>
对于那些使用 redux 的人,我使用了 extraData
prop 并在那里添加了加载我也做了我创建了一个名为 usePrevious
的自定义挂钩
import {useEffect, useRef} from 'react';
export const usePrevious = <T>(value: T): T | undefined => {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
并像这样用在我的物品上。
const prevData = usePrevious({data});
//CODES...
useEffect(() => {
if (prevData?.data === undefined) {
return;
}
if (prevData?.data?.someID !== data?.someId) {
// do something.
showSubChildren(false)
}
}, [data?.AuctionName, prevData, resetItemStates]);
所以这里基本上发生的事情是,您的项目将检查数据是否来自 undefined
(第一次)。然后它将检查某些数据 属性 是否已更改,如果已更改,您应该做一些事情。
像下面那样做将立即使 flatlist 项目更改立即反映出来。如果您不使用 redux,您也可以在组件中执行类似的操作。
let list = Object.assign([], state.auctionList);
let objIndex;
//Find index of specific object using findIndex method.
objIndex = list.findIndex(
obj => obj.auction_vehicles.vehicle_id == payload.vehicle_id,
);
// //Update object's property.
list[objIndex].auction_vehicles.time_left = payload.offer_expiry_time;
list[objIndex].auction_vehicles.starting_price = payload.amount;
list[objIndex].auction_vehicles.bidding_status =
payload.highest_bidder_flag;
return { ...state, auctionList: list };
与 ListView 不同,我们可以更新 this.state.datasource。是否有更新或重新渲染 FlatList 的方法或示例?
我的目标是在用户按下按钮时更新文本值...
renderEntries({ item, index }) {
return(
<TouchableHighlight onPress={()=> this.setState({value: this.state.data[index].value+1})>
<Text>{this.state.data[index].value}</Text>
</TouchableHighlight>
)
}
<FlatList
ref={(ref) => { this.list = ref; }}
keyExtractor={(item) => item.entry.entryId}
data={this.state.data}
renderItem={this.renderEntries.bind(this)}
horizontal={false} />
如果您要有一个按钮,您可以使用 onPress 中的 setState 更新数据。然后 SetState 将重新呈现您的 FlatList。
在 FlatList 组件上使用 extraData
属性。
如文档所述:
By passing
extraData={this.state}
toFlatList
we make sureFlatList
will re-render itself when thestate.selected
changes. Without setting this prop,FlatList
would not know it needs to re-render any items because it is also aPureComponent
and the prop comparison will not show any changes.
哦,很简单,用extraData
你看到额外数据在幕后工作的方式是 FlatList 或 VirtualisedList 只是通过检查 wether that object has changed正常 onComponentWillReceiveProps
方法。
所以你所要做的就是确保你提供的东西会改变extraData
。
这是我的做法:
我正在使用 immutable.js 所以我所做的就是传递一个 Map(不可变对象),其中包含我想观看的内容。
<FlatList
data={this.state.calendarMonths}
extraData={Map({
foo: this.props.foo,
bar: this.props.bar
})}
renderItem={({ item })=>((
<CustomComponentRow
item={item}
foo={this.props.foo}
bar={this.props.bar}
/>
))}
/>
这样,当 this.props.foo
或 this.props.bar
发生变化时,我们的 CustomComponentRow
也会更新,因为不可变对象将与之前的对象不同。
我已将 FlatList
替换为 SectionList
并且它会在状态更改时正确更新。
<SectionList
keyExtractor={(item) => item.entry.entryId}
sections={section}
renderItem={this.renderEntries.bind(this)}
renderSectionHeader={() => null}
/>
唯一需要记住的是 section
有 diff 结构:
const section = [{
id: 0,
data: this.state.data,
}]
要获得快速简单的解决方案,请尝试:
将额外数据设置为布尔值。
extraData={this.state.refresh}
想要re-render/refresh列表时切换布尔状态的值
this.setState({ refresh: !this.state.refresh })
对我来说,诀窍是 extraData 并再次深入到项目组件
state = {
uniqueValue: 0
}
<FlatList
keyExtractor={(item, index) => item + index}
data={this.props.photos}
renderItem={this.renderItem}
ItemSeparatorComponent={this.renderSeparator}
/>
renderItem = (item) => {
if(item.item.selected) {
return ( <Button onPress={this.itemPressed.bind(this, item)}>Selected</Button> );
}
return ( <Button onPress={this.itemPressed.bind(this, item)}>Not selected</Button>);
}
itemPressed (item) {
this.props.photos.map((img, i) => {
if(i === item.index) {
if(img['selected') {
delete img.selected;
} else {
img['selected'] = true;
}
this.setState({ uniqueValue: this.state.uniqueValue +1 });
}
}
}
将您的互动更改的变量放在 extraData
你可以发挥创意。
例如,如果您正在处理一个带有复选框的更改列表。
<FlatList
data={this.state.data.items}
extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
renderItem={({item}) => <View>
OK.I 刚刚发现,如果我们想让 FlatList 知道 data prop 之外的数据变化,我们需要将它设置为 extraData,所以我现在这样做:
<FlatList data={...} extraData={this.state} .../>
参考:https://facebook.github.io/react-native/docs/flatlist#extradata
我通过添加 extraData={this.state}
解决了这个问题,请查看下面的代码了解更多详情
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.arr}
extraData={this.state}
renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
/>
</View>
);
}
如果我们想让FlatList知道数据变化prop和state,我们可以构造一个同时引用prop和state的对象并刷新平面列表。
const hasPropOrStateChange = { propKeyToWatch: this.props, ...this.state};
<FlatList data={...} extraData={this.hasPropOrStateChange} .../>
文档:https://facebook.github.io/react-native/docs/flatlist#extradata
经过大量搜索和寻找真正的答案后,我终于得到了我认为最好的答案:
<FlatList
data={this.state.data}
renderItem={this.renderItem}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
ItemSeparatorComponent={this.renderSeparator}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={1}
extraData={this.state.data}
removeClippedSubviews={true}
**keyExtractor={ (item, index) => index }**
/>
.....
我的主要问题是 (KeyExtractor) 我没有像这样使用它。 不工作:keyExtractor={ (item) => item.ID} 在我改成这个之后它就像魅力一样工作 我希望这对某人有所帮助。
只需使用:
onRefresh={true}
在您的 flatList
组件中。
在react-native-flatlist中,它们是一个叫做extraData的属性。将以下行添加到您的平面列表中。
<FlatList
data={data }
style={FlatListstyles}
extraData={this.state}
renderItem={this._renderItem}
/>
在此示例中,要强制重新渲染,只需更改变量 machine
const [selected, setSelected] = useState(machine)
useEffect(() => {
setSelected(machine)
}, [machine])
Flatlist 的 extraData 对我不起作用,我碰巧使用了 redux 的 prop。这听起来与 ED209 的回答中的评论中的问题类似。当我收到道具时,我最终手动调用了 setState。
componentWillReceiveProps(nextProps: StateProps) {
if (this.props.yourProp != null && nextProps.yourProp) {
this.setState({ yourState: processProp(nextProps.yourProp) });
}
}
<FlatList
data={this.state.yourState}
extraData={this.state.yourState}
/>
对于那些使用 > React 17 的人,请使用 getDerivedStateFromProps
这里只是对之前答案的扩展。 要确保两部分,确保您添加了 extraData 并且您的 keyExtractor 是唯一的。如果您的 keyExtractor 是常量,则不会触发重新渲染。
<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
</FlatList>
我正在使用功能组件,因为我正在使用 Flatlist 和 redux 数据。 我正在使用 Redux store 管理所有状态。 这是在 api 调用后更新 Flatlist 数据的解决方案。
我第一次是这样做的:-
const DATA = useSelector((state) => state.address.address);
<FlatList
style = {styles.myAddressList}
data = {DATA}
renderItem = {renderItem}
keyExtractor = {item => item._id}
ListEmptyComponent = {EmptyList}
ItemSeparatorComponent={SeparatorWhite}
extraData = {refresh}
/>
但数据根本没有重新呈现我的 Flatlist 数据。
作为我喜欢的解决方案,如下所示:-
<FlatList
style = {styles.myAddressList}
data = {useSelector((state) => state.address.address)}
renderItem = {renderItem}
keyExtractor = {item => item._id}
ListEmptyComponent = {EmptyList}
ItemSeparatorComponent={SeparatorWhite}
/>
我将 Redux 状态直接传递给 Flatlist 数据源,而不是将其分配给变量。
谢谢。
const [itemSelected, setItemSelected] = setState(null);
....
const FlatListItem = (item) => {
return (
<TouchableOpacity onPress={() => setItemSelected(item.id)}>
<View style={ (itemSelected === item.id) ? style.itemWrapperActive : style.itemWrapper }>
<Text>{ item.label }</Text>
</View>
</TouchableOpacity>
)
}
....
<FlatList
ItemSeparatorComponent={() => <View style={{ width: 20 }} />}
data={ flatListData }
renderItem={ ({item}) => FlatListItem(item) }
keyExtractor={ (item) => item.id }
extraData={ itemSelected }
/>
对于那些使用 redux 的人,我使用了 extraData
prop 并在那里添加了加载我也做了我创建了一个名为 usePrevious
import {useEffect, useRef} from 'react';
export const usePrevious = <T>(value: T): T | undefined => {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
并像这样用在我的物品上。
const prevData = usePrevious({data});
//CODES...
useEffect(() => {
if (prevData?.data === undefined) {
return;
}
if (prevData?.data?.someID !== data?.someId) {
// do something.
showSubChildren(false)
}
}, [data?.AuctionName, prevData, resetItemStates]);
所以这里基本上发生的事情是,您的项目将检查数据是否来自 undefined
(第一次)。然后它将检查某些数据 属性 是否已更改,如果已更改,您应该做一些事情。
像下面那样做将立即使 flatlist 项目更改立即反映出来。如果您不使用 redux,您也可以在组件中执行类似的操作。
let list = Object.assign([], state.auctionList);
let objIndex;
//Find index of specific object using findIndex method.
objIndex = list.findIndex(
obj => obj.auction_vehicles.vehicle_id == payload.vehicle_id,
);
// //Update object's property.
list[objIndex].auction_vehicles.time_left = payload.offer_expiry_time;
list[objIndex].auction_vehicles.starting_price = payload.amount;
list[objIndex].auction_vehicles.bidding_status =
payload.highest_bidder_flag;
return { ...state, auctionList: list };