React-Native 另一个 VirtualizedList 支持的容器
Posted
技术标签:
【中文标题】React-Native 另一个 VirtualizedList 支持的容器【英文标题】:React-Native another VirtualizedList-backed container 【发布时间】:2020-02-03 05:19:36 【问题描述】:升级到 react-native 0.61 后,我收到很多这样的警告:
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.
我应该使用的另一个VirtualizedList-backed container
是什么,为什么现在建议不要那样使用?
【问题讨论】:
您能否为您的问题提供完整的警告信息?因为用你现在的标题很难找到。 仅针对可能遇到与我相同问题的任何人,这是因为我将<FlatList />
封装在<ScrollView />
中
如果 FlatList 中没有更多项目,只需在 ScrollView 内渲染项目而不使用 FlatList
【参考方案1】:
如果有人仍在寻找关于 @Ponleu 和 @David Schilling 在这里描述的问题的建议(关于 FlatList 上方的内容),那么这就是我采取的方法:
<SafeAreaView style=flex: 1>
<FlatList
data=data
ListHeaderComponent=ContentThatGoesAboveTheFlatList
ListFooterComponent=ContentThatGoesBelowTheFlatList />
</SafeAreaView>
您可以在此处阅读更多信息:https://facebook.github.io/react-native/docs/flatlist#listheadercomponent
希望它可以帮助某人。 :)
【讨论】:
你知道为什么这应该比产生警告的方式更好吗? @DavidSchilling 因为您尝试使用 2 个滚动容器的结果的方式:ScrollView
和 FlatList
- 您将获得不一致的滚动行为。此答案中提出的方式仅产生 1 个滚动容器,并且在页眉/页脚中,您可以放置任何视图,无论多么复杂。
我正在使用函数组件,并遇到 ContentThatGoesAboveTheFlatList 重新渲染问题。对此的任何解决方案
@Ponleu 您可以使用 React 提供的 useMemo
挂钩来记忆您的 ContentThatGoesAboveTheFlatList 组件,以避免重新渲染。更多信息在这里:reactjs.org/docs/hooks-reference.html#usememo 如果有帮助,请告诉我。 :)
我需要在一个页面中包含两个包含不同数据集的平面列表...我该怎么办?【参考方案2】:
以防万一这对某人有所帮助,这就是我在我的案例中修复错误的方法。
我有一个 FlatList
嵌套在 ScrollView
中:
render()
return (
<ScrollView>
<Text>'My Title'</Text>
<FlatList
data=this.state.myData
renderItem=( item ) =>
return <p>item.name</p>;
/>
this.state.loading && <Text>'Loading...'</Text>
</ScrollView>
);
我摆脱了ScrollView
,使用FlatList
渲染我需要的一切,从而摆脱了警告:
render()
const getHeader = () =>
return <Text>'My Title'</Text>;
;
const getFooter = () =>
if (this.state.loading)
return null;
return <Text>'Loading...'</Text>;
;
return (
<FlatList
data=this.state.myData
renderItem=( item ) =>
return <p>item.name</p>;
ListHeaderComponent=getHeader
ListFooterComponent=getFooter
/>
);
【讨论】:
致寻找最佳答案的人:“选择这个。仅使用一个 FlatList。”【参考方案3】:最好的方法是禁用该警告,因为有时Flatlist
需要在ScrollView
中。
更新 RN V0.63 以上
YellowBox
现在已更改并替换为 LogBox
功能性
import React, useEffect from 'react';
import LogBox from 'react-native';
useEffect(() =>
LogBox.ignoreLogs(['VirtualizedLists should never be nested']);
, [])
基于类
import React from 'react';
import LogBox from 'react-native';
componentDidMount()
LogBox.ignoreLogs(['VirtualizedLists should never be nested']);
在下面更新 RN V0.63
功能性
import React, useEffect from 'react';
import YellowBox from 'react-native';
useEffect(() =>
YellowBox.ignoreWarnings(['VirtualizedLists should never be nested']);
, [])
基于类
import React from 'react';
import YellowBox from 'react-native';
componentDidMount()
YellowBox.ignoreWarnings(['VirtualizedLists should never be nested']);
【讨论】:
我有一个打开对话框的按钮,其中有一个输入框。当我单击输入时,对话框立即消失。所以我不得不用 ScrollView 包装 FlatList。那正在解决问题,但会导致警告。我发现的解决方案都没有奏效。所以在这种情况下,我完全同意尼沙格的观点。如果有人找到解决方案,请通知我。 这似乎是我唯一的方法,没有其他建议可以帮助我,使用除了滚动视图之外的其他组件是行不通的! 你知道,警告是有原因的,你不应该忽略它们...... 同意,但有时我们需要因为一些低版本的依赖关系 @RafaelTavares,那么为什么这些被忽略的函数存在呢?【参考方案4】:出现警告是因为ScrollView
和FlatList
共享相同的逻辑,如果FlatList
在ScrollView
中运行,则会重复
顺便说一下SafeAreaView
对我不起作用,唯一的解决方法是
<ScrollView>
data.map((item, index) =>
...your code
</ScrollView>
错误消失
【讨论】:
这个对我有用。我需要在Scrollview
中的 Flatlist
和你在这里建议的旧的 map
函数为我做了它!
不明白这个。地图有什么帮助? FlatList 去哪儿了?
想法正确,但代码不起作用。【参考方案5】:
查看文档中的示例,我已从以下位置更改容器:
<ScrollView>
<FlatList ... />
</ScrollView>
到:
<SafeAreaView style=flex: 1>
<FlatList ... />
</SafeAreaView>
所有这些警告都消失了。
【讨论】:
如果我将内容呈现在FlatList
内部ScrollView
并希望该内容可滚动?
两个可滚动的视图并排放置并不是很好的用户体验。我会尝试像这样嵌套它:'ScrollView
,然后在ScrollView
里面还有一个FlatList
。我希望整个屏幕一起滚动。
<SafeAreaView>
仅适用于 ios 11 或更高版本 (facebook.github.io/react-native/docs/safeareaview)
ScrollView
的主要目的是让它可以垂直滚动。获取该属性不会使其再次可滚动。这里有什么意义?【参考方案6】:
解决方案 #1
// dummy data array
const data = [
id: 1, name: 'Tom',
id: 2, name: 'Jerry',
]
你也可以像这样为它制作一个自定义组件
const VirtualizedList = (children) =>
return (
<FlatList
data=[]
keyExtractor=() => "key"
renderItem=null
ListHeaderComponent=
<>children</>
/>
)
然后使用这个 VirtualizedList 作为父组件:
...
return (
<VirtualizedList>
<FlatList
data=data
keyExtractor=(item, index) => item.id + index.toString()
renderItem=_renderItem
/>
<AnyComponent/>
</VirtualizedList>
)
解决方案 #2
如果您在 ScrollView 中使用 FlatList,它会发出令人讨厌的警告,因此您可以像这样使用数组的 map 属性 -
<ScrollView>
data.map((item, index) => (
<View key=index>
<Text>item.name</Text>
</View>
))
</ScrollView>
解决方案 #3
如果您将 FlatList 设为水平(根据您的需要),那么警告也会消失
<ScrollView>
<FlatList
data=data
keyExtractor=(item, index) => item.id + index.toString()
horizontal=true
/>
</ScrollView>
解决方案 #4
可以添加页眉和页脚组件
在 ListHeaderComponent 和 ListFooterComponent 中你可以添加任何组件,这样你就不需要父 ScrollView
<FlatList
data=data
keyExtractor=(item, index) => item.id + index.toString()
ListHeaderComponent=headerComponent
ListFooterComponent=footerComponent
ListEmptyComponent=emptyComponent
ItemSeparatorComponent=separator
/>
// List components
const headerComponent = () => (
<View>
<Header/>
<Any/>
</View>
)
const footerComponent = () => (
<View>
<Footer/>
<Any/>
</View>
)
const emptyComponent = () => (
<View>
<EmptyView/>
<Any/>
</View>
)
const separator = () => (
<View style=height: 0.8, width: '100%', backgroundColor: '#fff' />
)
【讨论】:
FlatList 通常用于动态加载和显示数据。在大多数情况下,将其转换为静态列表并不是一种方法。 它工作得很好,可能是你做错了什么。 在我的情况下,horizontal=false 成功了,因为水平=true 将导致 FlatList 水平渲染项目,这是没人想要的... 正如我上面所说,根据您的要求将其设置为horizontal=true。【参考方案7】:在 my case 中,我需要将 FlatLists 嵌套在 ScrollView 中,因为我使用 react-native-draggable-flatlist 在配方中移动成分和步骤。
如果我们正确阅读警告,它说我们应该使用另一个 VirtualizedList 支持的容器来嵌套我们的子 FlatList。我所做的是:
/* outside the component */
const emptyArry = []
/* render */
<FlatList
scrollEnabled=false
horizontal
data=emptyArray
ListEmptyComponent=(<DraggableList />)
/>
没有更多警告,我认为这是警告推荐的模式。
【讨论】:
【参考方案8】:正如@Brahim 上面所说,将horizontal
属性设置为true
似乎可以解决嵌入在ScrollView
中的FlatList
的问题。
【讨论】:
我不知道为什么这么多人提到horizontal
属性解决方案,这完全破坏了我的设计,我相信其他人也是如此
如果使用numColumns
属性,那么horizontal
属性将完全破坏它。【参考方案9】:
我尝试了一些方法来解决这个问题,包括ListHeaderComponent
或ListFooterComponent
,但都不适合我。
我想实现的布局是这样的,我想滚进去一次。
<ScrollView>
<View>I'm the first view</View>
<View>I'm the second view</View>
<MyFlatList />
</ScrollView>
首先我要感谢this issue 和 cmets,它们给了我很多想法。
我正在考虑将ListHeaderComponent
放在平面列表上方,但由于我的Flatlist
的方向是列,所以我想放置的标题位于Flatlist
的左侧:(
然后我不得不尝试VirtualizedList-backed
的东西。我只是尝试将所有组件打包在VirtualizedList
中,其中renderItems
提供索引,我可以有条件地将组件传递给renderItems
。
我本可以使用 Flatlist
进行此操作,但我还没有尝试过。
最后它看起来像这样。
<View>
<Virtualizedlist
data=[]
initialNumToRender=1
renderItem=(props)=>
props.index===0 ? (1st view here) : props.index===1 ? (2nd view here) : (my flatlist)
keyExtractor=item => item.key
getItemCount=2
getItem= (data, index) =>
return
id: Math.random().toString(12).substring(0),
/>
</View>
(inside which lazyly renders↓)
<View>I'm the first view</View>
<View>I'm the second view</View>
<MyFlatList />
当然可以滚动整个屏幕。
【讨论】:
【参考方案10】:所以我在 <ScrollView>
中使用基于选择器的组件时遇到了同样的问题,而帮助我解决问题的一件事是添加
keyboardShouldPersistTaps=true
在 <ScrollView>
中作为道具。
这是我的代码 sn-p。
<ScrollView keyboardShouldPersistTaps=true>
<SelectionDD studentstatus=studentStatus/>
<SearchableDD collegeNames=collegeNames placeholder='University'/>
</ScrollView>
【讨论】:
不推荐使用 .. 必须是 keyboardShouldPersistTaps="always" 我不确定它最近是否发生了变化。但是非常感谢您提供的信息!【参考方案11】:<ScrollView horizontal=false style=width: '100%', height: '100%'>
<ScrollView horizontal=true style=width: '100%', height: '100%'>
<FlatList ... />
</ScrollView>
</ScrollView>
【讨论】:
【参考方案12】:在我看来,我可以使用地图而不是 FlatList。但就我而言,我不想显示大列表。不使用 FlatList 可能会导致性能问题。所以我用它来抑制警告https://github.com/GeekyAnts/NativeBase/issues/2947#issuecomment-549210509
【讨论】:
【参考方案13】:由于在 ScrollView 中使用 FlatList,此错误消失了。你可以像下面这样写代码。
<SafeAreaView style=styles.container>
<View style=styles.container>
<View>
<Header />
</View>
(list.length == 0) &&
<View style=flex:1, margin: 15>
<Text style=textAlign: 'center'>No peripherals</Text>
</View>
<FlatList
data=list
renderItem=( item ) => this.renderItem(item)
keyExtractor=item => item.id
/>
</View>
</SafeAreaView>
【讨论】:
【参考方案14】:在不隐藏 YellowBox 的情况下,您仍然可以在可滚动视图中实现可滚动视图。您可以使用this library。它取代了 React Native 中的默认 Scrollview。
【讨论】:
【参考方案15】:这可能会对其他人有所帮助,请务必检查组件的嵌套方式。从顶部组件中移除 ScrollView 解决了这个问题。
我遇到了这个问题,因为我基本上有两个这样嵌套的组件:
组件 1
<ScrollView>
<OtherStuff />
<ListComponent />
</ScrollView>
我的第二个组件“ListComponent”有一个 FlatList 已经用 SafeAreaView 包装。
<SafeAreaView style=styles.container>
<FlatList
data=todoData
renderItem=renderItem
ItemSeparatorComponent=() => <View style=styles.separator />
keyExtractor=item => item.id.toString()
/>
</SafeAreaView>
最后我用 View 替换了第一个组件中的 ScrollView。
【讨论】:
【参考方案16】:事实上,据我所知,使用嵌套的 VirtualizedLists 总是会导致性能问题,只是对该问题的警告是新的。我尝试了我在互联网上找到的所有内容,但没有一个有帮助。我现在使用 ScrollView,或者当您只有一个带有 maxHeight 的普通视图时,如果内容高度大于您视图的 maxHeight,您将能够滚动。 所以:
<ScrollView>
items.map((item, index) =>
<YourComponent key=index item=item />
)
</ScrollView>
或者只是:
<View style=maxHeight: MAX_HEIGHT>
items.map((item, index) =>
<YourComponent key=index item=item />
)
</View>
【讨论】:
FlatList 通常用于动态加载和显示数据。在大多数情况下,将其转换为静态列表并不是一种方法。【参考方案17】:我遇到了同样的问题,只是通过删除 FlatList 周围的 ScrollView 来解决它。因为默认情况下,FlatList 根据其呈现的内容长度提供滚动功能。 ?
【讨论】:
如果您在同一屏幕上有与 FlatList 同级的其他内容/组件,这将不起作用。以上是关于React-Native 另一个 VirtualizedList 支持的容器的主要内容,如果未能解决你的问题,请参考以下文章
如何将 state 下的数据导出到另一个文件?(react-native)
React-Native:在另一个类中访问 TextField 值
如何在 react-native 中将函数的结果从一个组件传递到另一个组件?