当几次到达FlatList的底部时,响应本地火灾事件

时间:2020-10-01 13:07:24

标签: react-native react-native-flatlist

我正在尝试在react native中建立聊天,并希望每次到达时都检查是否到达FlatList的底部,因此在打开键盘和用户之前位于列表的末尾(如果她不在列表末尾,我不想向下滚动)。

我当然可以打电话给onEndReached,但是在加载所有消息时,它只会触发一次。

所以我在编码以下内容,但问自己是否有更好的方法来实现这一点:

我的状态和我的FlatList参考:

  const [messageInputFocus, setmessageInputFocus] = useState(false);
  const [
    messagesListDistanceFromEnd,
    setMessagesListDistanceFromEnd,
  ] = useState(0);
  const [messagesListScrollYPos, setMessagesListScrollYPos] = useState(0);
  const inboxThreadFlatList = useRef<FlatList>(null);

在输入消息时使用useEffect:

  useEffect(() => {
    if (messagesListDistanceFromEnd === messagesListScrollYPos) {
      inboxThreadFlatList.current?.scrollToEnd({ animated: true });
    }
  }, [messageInputFocus]);

  const onScrollMessagesList = (
    event: NativeSyntheticEvent<NativeScrollEvent>
  ) => {
    setMessagesListScrollYPos(event.nativeEvent.contentOffset.y);
  };

我的FlatList在底部带有onEndReached和onScroll方法:

          <FlatList
            data={messages.records}
            renderItem={({ item, index }) => {
              return (
                <View
                  style={
                    index === messages.length - 1 ? { paddingBottom: 68 } : {}
                  }
                >
                  {userMe.id === item.sender ? (
                    <View
                      style={[
                        styles.messageContainer,
                        styles.messageSentContainer,
                      ]}
                    >
                      <View>
                        <Text
                          style={[styles.messageText, styles.messageSentText]}
                        >
                          {item.message}
                        </Text>
                        <View
                          style={[styles.triangle, styles.triangleSent]}
                        ></View>
                      </View>
                    </View>
                  ) : (
                    <View
                      style={[
                        styles.messageContainer,
                        styles.messageReceivedContainer,
                      ]}
                    >
                      <View>
                        <Text
                          style={[
                            styles.messageText,
                            styles.messageReceivedText,
                          ]}
                        >
                          {item.message}
                        </Text>
                        <View
                          style={[styles.triangle, styles.triangleReceived]}
                        ></View>
                      </View>
                    </View>
                  )}
                </View>
              );
            }}
            ref={inboxThreadFlatList}
            keyExtractor={(item, index) => index.toString()}
            initialScrollIndex={messages.length - 1}
            onScrollToIndexFailed={(info) => {
              const wait = new Promise((resolve) => setTimeout(resolve, 500));
              wait.then(() => {
                inboxThreadFlatList.current?.scrollToIndex({
                  index: info.index,
                  animated: true,
                });
              });
            }}
            onEndReached={({ distanceFromEnd }) => {
              setMessagesListDistanceFromEnd(distanceFromEnd);
            }}
            onScroll={onScrollMessagesList}
          />

代码像这样工作。但是再说一次,有没有更好的方法,因为我将滚动位置设置为一个状态并问自己,这是否是性能问题?

1 个答案:

答案 0 :(得分:0)

所以有一个原因导致FlatList上的inverted存在:)

如果FlatList被反转,我可以检查event.nativeEvent.contentOffset.y是否为零,然后像这样设置一次状态:

const onScrollMessagesList = (
    event: NativeSyntheticEvent<NativeScrollEvent>
) => {
    if (event.nativeEvent.contentOffset.y === 0 && !messagesListScrolledToEnd) {
         setMessagesListScrolledToEnd(true);
    } else if (messagesListScrolledToEnd) {
         setMessagesListScrolledToEnd(false);
    }
};

然后检查我的TextInput是否聚焦,如果滚动,则滚动到索引0:

useEffect(() => {
    if (messagesListScrolledToEnd) {
      scrollToBottom();
    }
}, [messageInputFocus]);

const scrollToBottom = () => {
    setTimeout(() => {
      inboxThreadFlatList.current?.scrollToIndex({
        animated: true,
        index: 0,
      });
    }, 50);
};

我希望这对任何人都有帮助。

相关问题