React Native 更新平面列表数据后ScrollToEnd

x8goxv8g  于 2023-01-31  发布在  React
关注(0)|答案(8)|浏览(208)

我正在用Flatlist制作一个聊天框。我想添加一个新项目到数据中,然后滚动到列表的底部。我使用scrollToEnd方法,但它不起作用。我该怎么做呢?

<FlatList
        ref="flatList"
        data={this.state.data}
        extraData = {this.state}
        renderItem={({item}) => <Text style={styles.chatFlatListItem}>{item.chat}</Text>}
/>

AddChat(_chat){
    var arr = this.state.data;
    arr.push({key: arr.length, chat: _chat});
    var _data = {};
    _data["data"] = arr;
    this.setState(_data);
    this.refs.flatList.scrollToEnd();
 }
cuxqih21

cuxqih211#

我找到了一个更好的解决方案,scrollToEnd()不起作用,因为它是在对FlatList进行更改之前触发的。
因为它继承自ScrollView,所以这里最好的方法是在onContentSizeChange中调用scrollToEnd(),如下所示:

<FlatList
            ref = "flatList"
            onContentSizeChange={()=> this.refs.flatList.scrollToEnd()} />
nr7wwzry

nr7wwzry2#

感谢@Kernael,只需添加如下超时:

setTimeout(() => this.refs.flatList.scrollToEnd(), 200)
rfbsl7qr

rfbsl7qr3#

const flatList = React.useRef(null)
<FlatList
        ref={flatList}
        onContentSizeChange={() => {
            flatList.current.scrollToEnd();
        }}
        data={this.state.data}
        extraData = {this.state}
        renderItem={({item}) => <Text style={styles.chatFlatListItem}>{item.chat}</Text>}
/>

试试这个,管用。

unguejic

unguejic4#

我的问题是scrollToEnd()在移动的上运行良好,但在网络上总是滚动到顶部。可能是因为我在FlatList中有不同大小的元素,无法定义getItemLayout。但感谢accepted answer,我解决了这个问题。只是方法不同。

const ref = React.useRef<FlatList>();

function handleScrollToEnd(width, height) {
  if (ref.current) {
    ref.current.scrollToOffset({offset: height});
  }
}

<FlatList
  ref={ref}
  onContentSizeChange={handleScrollToEnd} 
/>

这在移动的和网络上都很有效。希望对某些人有帮助。

2jcobegt

2jcobegt5#

修改你的代码如下。ref被修改,最好在你的FlatList中使用getItemLayout

AddChat(_chat){
    var arr = this.state.data;
    arr.push({key: arr.length, chat: _chat});
    var _data = {};
    _data["data"] = arr;
    this.setState(_data);
    this.flatList.scrollToEnd();
 }

<FlatList
    ref={elm => this.flatList = elm}
    data={this.state.data}
    extraData = {this.state}
    renderItem={({item}) => <Text style={styles.chatFlatListItem}>{item.chat}</Text>}
    getItemLayout={(data, index) => (
      {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
    )}
/>

**注意:**请将ITEM_HEIGHT替换为列表项高度的真实的值。

wwtsj6pe

wwtsj6pe6#

1.尝试对Fatlist本身使用反向推进
1.像这样传递数据[...data].reverse()
1.如果您位于列表的中间位置,并且在添加新项目时需要滚动到末尾,只需用途:

ref  => flatlistRef.current?.scrollToOffset({offset:0})
cclgggtu

cclgggtu7#

似乎是这条线造成的
https://github.com/facebook/react-native/blob/3da3d82320bd035c6bd361a82ea12a70dba4e851/Libraries/Lists/VirtualizedList.js#L1573
当使用触发器scrollToEnd时,帧偏移为0
https://github.com/facebook/react-native/blob/3da3d82320bd035c6bd361a82ea12a70dba4e851/Libraries/Lists/VirtualizedList.js#L390
如果等待1秒,_onContentSize将发生变化,且frame.offset将被赋值(例如,1200像素)。
相关帖子https://github.com/facebook/react-native/issues/30373#issuecomment-1176199466

g6baxovj

g6baxovj8#

只需在Flatlist呈现之前添加一个加载器即可。

const flatListRef = useRef(null);
const [messages, setMessages] = useState([]);

 if(!messages.length){
   return <Loader />
   }

return (
    <View style={styles.messagesContainer}>
      <FlatList
        ref={flatListRef}
        data={messages}
        onContentSizeChange={() => {
          if (flatListRef.current) {

          flatListRef?.current?.scrollToEnd();

          }
        }}
        renderItem={({item, index}) => {
          return (
            <DisplayMessages
              message={item}
              index={index}
            />
          );
        }}
      />
    </View>

相关问题