如何重新渲染平面列表?
Posted
技术标签:
【中文标题】如何重新渲染平面列表?【英文标题】:How to re-render flatlist? 【发布时间】:2017-09-09 21:40:03 【问题描述】:与 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 />
【问题讨论】:
docs for FlatList 说“这是一个PureComponent
,这意味着如果道具保持浅相等,它将不会重新渲染。确保您的renderItem
函数所依赖的所有内容都传递为更新后不是 ===
的道具,否则您的 UI 可能不会在更改时更新。这包括 data
道具和父组件状态。您是否遵循此建议?
无论我用extraData
和shouldItemUpdate
尝试什么,我都无法让列表重新渲染。我最终做的是清除状态,等待渲染然后更新状态。 this.setState( data: null , () => this.setState( data: actualData ) );
【参考方案1】:
在您的 FlatList 组件上使用 extraData
属性。
如文档所述:
通过将
extraData=this.state
传递给FlatList
,我们确保FlatList
将在state.selected
更改时重新呈现自己。如果不设置此道具,FlatList
将不知道需要重新渲染任何项目,因为它也是PureComponent
,并且道具比较不会显示任何更改。
【讨论】:
我正在使用 redux,在这种情况下发送像data=this.props.searchBookResults
这样的数据,extraData=this.state
和 extraData=this.props
都不适合我。而data=this.props.searchBookResults
也不起作用。怎么办?
使用 extraData: 刷新你的 ... data=this.props.searchBookResults extraData=this.state.refresh onPress=()=this.setState( refresh: !refresh)
extraData
,组件不会更新:(
@DenisCappelini,确保当子项[s] 必须重新渲染时,传递到 extraData
属性的数据会发生变化。例如,如果列表项可以是活动/非活动的,请确保状态变量,无论是this.state
对象还是this.props
对象的一部分,都应该进入extraData
。它可能是一个光标,也可能是一个活动项目数组等。
@Sujit 我遇到了同样的问题,但后来我意识到我已经实现了shouldComponentUpdate()
,一旦我更新或完全注释掉,事情就像文档中描述的那样工作。
【参考方案2】:
如需快速简单的解决方案,请尝试:
将额外数据设置为布尔值。
extraData=this.state.refresh
当你想重新渲染/刷新列表时切换布尔状态的值
this.setState(
refresh: !this.state.refresh
)
【讨论】:
这正是我所需要的,因为我将向 data 道具添加数据。此外,这是 React-Native 团队的一个超级怪异的实现……在数据上拥有刷新功能或属性会更有意义。即:this.data.refresh()
。相反,我们设置一个布尔值并更改它。布尔值本身没有意义,那么它存在的意义何在?...(没有意义,除了让数据刷新对吗?)
@HradeshKumar 我这样做了,但 Data 中的最后一项不能消失!
这就像魅力一样,但我仍然不知道为什么this.state.users
不起作用,即使我正在更改某些用户的标志。
对我不起作用,你能帮忙吗:***.com/questions/65547030/…
你好,希望你很好,你能帮我解决这个问题吗? ***.com/questions/65769926/…【参考方案3】:
哦,这很简单,只需使用extraData
您会看到额外数据在幕后工作的方式是 FlatList 或 VirtualisedList 只是通过普通的 onComponentWillReceiveProps
方法检查 wether that object has changed。
所以你所要做的就是确保你给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
将更新,因为不可变对象将与之前的对象不同。
【讨论】:
我终于明白extraData
了!感谢VirtualisedList
代码的链接!
你好,@SudoPiz 我想在删除最后一项后重新渲染Flatlist,可以查看这个Q ***.com/questions/58780167/…【参考方案4】:
好的。我刚刚发现如果我们想让 FlatList 知道 data 属性之外的数据变化,我们需要将它设置为 extraData,所以我现在这样做:
<FlatList data=... extraData=this.state .../>
参考:https://facebook.github.io/react-native/docs/flatlist#extradata
【讨论】:
最好的实现......我更喜欢将它设置为与 data 属性相同,因此当状态发生任何变化时它不会刷新,但这是迄今为止最简单的实现。谢谢! 你好,@MahdiBashirpour 我想在删除最后一项后重新渲染 Flatlist,可以查看这个 Q ***.com/questions/58780167/… 你好,希望你很好,你能帮我解决这个问题吗? ***.com/questions/65769926/… 嗨,马赫迪,你能看看这个问题吗? ***.com/questions/65786115/…【参考方案5】:如果您要拥有一个 Button,您可以在 onPress 中使用 setState 更新数据。然后 SetState 将重新渲染您的 FlatList。
【讨论】:
我的 touchablehighlight 中有一个 setState。 setState 工作正常,但平面列表未显示状态值的更新 -> this.state.value 您的 FlastList 中的值没有更新,因为您没有直接更新数据源。 this.state.data 是使用 FlatList 呈现的内容,但在 onPress 中您只更新 this.state.value。 对不起,我的错误,问题错字。应该是 this.state.data[index].value【参考方案6】:经过大量搜索和寻找真正的答案,我终于得到了我认为最好的答案:
<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 在我改成这个之后,它就像魅力一样 我希望这对某人有帮助。
【讨论】:
你能把this.state.refreshing
和函数handleRefresh
的值放在一起吗?【参考方案7】:
这里只是对先前答案的扩展。 要确保的两个部分,请确保您添加了 extraData 并且您的 keyExtractor 是唯一的。如果您的 keyExtractor 是常量,则不会触发重新渲染。
<FlatList
data=this.state.AllArray
extraData=this.state.refresh
renderItem=( item,index )=>this.renderPhoto(item,index)
keyExtractor=item => item.id
>
</FlatList>
【讨论】:
【参考方案8】:我通过添加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>
);
【讨论】:
【参考方案9】:在本例中,要强制重新渲染,只需更改变量machine
const [selected, setSelected] = useState(machine)
useEffect(() =>
setSelected(machine)
, [machine])
【讨论】:
【参考方案10】:我已将FlatList
替换为SectionList
,它会在状态更改时正确更新。
<SectionList
keyExtractor=(item) => item.entry.entryId
sections=section
renderItem=this.renderEntries.bind(this)
renderSectionHeader=() => null
/>
唯一需要记住的是section
有差异结构:
const section = [
id: 0,
data: this.state.data,
]
【讨论】:
你好,希望你很好,你能帮我解决这个问题吗? ***.com/questions/65769926/…【参考方案11】:对我来说,诀窍是 extraData 并再次深入到 item 组件中
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 在哪里?【参考方案12】:将您的交互更改的变量放在extraData
你可以有创意。
例如,如果您正在处理带有复选框的更改列表。
<FlatList
data=this.state.data.items
extraData=this.state.data.items.length * (this.state.data.done.length + 1)
renderItem=(item) => <View>
【讨论】:
【参考方案13】:如果我们想让 FlatList知道数据变化prop 和 state,我们可以构造一个引用 prop 和 state 的对象并刷新 flatlist。
const hasPropOrStateChange = propKeyToWatch: this.props, ...this.state;
<FlatList data=... extraData=this.hasPropOrStateChange .../>
文档:https://facebook.github.io/react-native/docs/flatlist#extradata
【讨论】:
【参考方案14】:在 react-native-flatlist 中,它们是一个称为 extraData 的属性。将以下行添加到您的平面列表中。
<FlatList
data=data
style=FlatListstyles
extraData=this.state
renderItem=this._renderItem
/>
【讨论】:
【参考方案15】:我正在使用功能组件,因为我正在使用带有 redux 数据的 Flatlist。 我正在使用 Redux 商店管理所有状态。 以下是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 数据源,而不是将其分配给变量。
谢谢。
【讨论】:
【参考方案16】: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
/>
【讨论】:
【参考方案17】:对于那些使用 redux 的人,我使用了 extraData
属性并在那里添加了加载,我还创建了一个名为 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
(第一次)。然后它会检查某些数据属性是否发生了变化,如果有,你应该做点什么。
【讨论】:
【参考方案18】:只需使用:
onRefresh=true
在您的 flatList
组件中。
【讨论】:
这会产生错误,然后你需要使用refreshing
prop【参考方案19】:
Flatlist 的 extraData 对我不起作用,我碰巧使用了来自 redux 的道具。这听起来类似于 ED209 答案中来自 cmets 的问题。当我收到道具时,我最终手动调用了 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
【讨论】:
以上是关于如何重新渲染平面列表?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Redux 添加更多数据时,带有分页结果的平面列表会导致重新渲染
如何实现 Activity 指示器进行渲染,直到显示平面列表数据?反应原生