Skip to content

Layout Shifts #389

@sujanChy00

Description

@sujanChy00

Having Layout shifts

below i have given video, repo link and some codes
i am new to react native world so please guide me through

[Repo URL](https://github.com/sujanChy00/tetoteto-seller/blob/master/components/chat/user-chat-list.tsx

import { UserChatList } from "@/components/chat/user-chat-list";
import { ChatProvider } from "@/context/chat-provider";
import { useKeyboardHeight } from "@/hooks/use-keyboard-height";
import { useGetUserMessagesById } from "@/query/chat";
import { Stack, useLocalSearchParams } from "expo-router";
import { Spinner } from "heroui-native";
import React, { useMemo } from "react";
import { View } from "react-native";
import Animated from "react-native-reanimated";

const MessageDetails = () => {
  const { userId } = useLocalSearchParams<{
    userId: string;
    orderId?: string;
  }>();
  const { animatedStyle } = useKeyboardHeight();

  const { data, isPending, hasNextPage, fetchNextPage, isFetchingNextPage } =
    useGetUserMessagesById(Number(userId));

  const { messages, canReply, user } = useMemo(() => {
    const firstPage = data?.pages[0];
    return {
      messages: data ? data.pages.flatMap((p) => p.content).toReversed() : [],
      canReply: firstPage?.canReply,
      user: firstPage?.user,
    };
  }, [data]);

  if (isPending)
    return (
      <View className="flex-1 items-center justify-center">
        <Spinner />
        <Stack.Screen
          options={{
            title: "Loading...",
          }}
        />
      </View>
    );

  return (
    <ChatProvider
      userId={Number(userId)}
      messages={messages}
      canReply={canReply || false}
      user={user}
      hasNextPage={hasNextPage}
      fetchNextPage={fetchNextPage}
      isFetchingNextPage={isFetchingNextPage}
    >
      <View className="flex-1 px-2 pb-safe">
        <UserChatList />
        <ChatActions />
        <Animated.View style={animatedStyle} />
      </View>
    </ChatProvider>
  );
};

export default MessageDetails;

import { IChatMessage } from "@/types";
import { LegendList } from "@legendapp/list";
import { Link, Stack } from "expo-router";
import { Button, cn } from "heroui-native";
import React, { useCallback } from "react";
import { View } from "react-native";
import { Chat } from ".";
import { ListFetchingMoreFooter } from "../list-fetching-more-footer";
import { ListFooterComponent } from "../list-footer-component";
import { ListSeparator } from "../list-separator";
import { StyledMaterialCommunityIcons } from "../styled-icons";
import { ThemedText } from "../themed-text";

export const UserChatList = () => {
  const {
    listRef,
    messages,
    hasNextPage,
    fetchNextPage,
    isFetchingNextPage,
    user,
    userId,
  } = useChat();

  const renderItem = useCallback(
    ({ item }: { item: IChatMessage }) => {
      const isCustomer = !item.admin && !item.user;
      return (
        <View
          className={cn("gap-0.5", isCustomer ? "items-end" : "items-start")}
        >
          <View className="gap-5">
            <Chat.Text chat={item} isCustomer={isCustomer} />
            <Chat.Image chat={item} isCustomer={isCustomer} />
            <Chat.Item chat={item} isCustomer={isCustomer} />
          </View>
          <Chat.Status chat={item} isCustomer={isCustomer} />
        </View>
      );
    },
    [messages],
  );

  if (messages.length === 0)
    return (
      <View className="flex-1 items-center justify-center gap-2">
        <StyledMaterialCommunityIcons
          name="message-outline"
          size={40}
          className="text-muted"
        />
        <ThemedText className="italic">No messages yet</ThemedText>
        <Stack.Screen
          options={{
            headerTitle: user?.name,
          }}
        />
      </View>
    );

  return (
    <React.Fragment>
      <Stack.Screen
        options={{
          headerTitle: user?.name,
          headerRight: () => (
            <Link
              asChild
              href={{
                pathname: "/[user-orders]",
                params: {
                  "user-orders": userId,
                },
              }}
            >
              <Button variant="ghost" size="sm">
                <Button.Label>view orders</Button.Label>
              </Button>
            </Link>
          ),
        }}
      />
      <LegendList
        ref={listRef}
        keyboardShouldPersistTaps="handled"
        scrollEventThrottle={16}
        estimatedItemSize={100}
        alignItemsAtEnd
        initialScrollIndex={messages.length - 1}
        maintainScrollAtEnd
        maintainScrollAtEndThreshold={0.1}
        ItemSeparatorComponent={() => <ListSeparator className="h-5" />}
        drawDistance={300}
        waitForInitialLayout
        recycleItems
        data={messages}
        renderItem={renderItem}
        showsVerticalScrollIndicator={false}
        keyExtractor={(item) => `chat-${item.id}`}
        onStartReachedThreshold={0.05}
        onStartReached={() => {
          if (hasNextPage && !isFetchingNextPage) {
            fetchNextPage();
          }
        }}
        ListHeaderComponentStyle={{
          alignItems: "center",
        }}
        ListFooterComponent={() => <ListFooterComponent className="h-5" />}
        ListHeaderComponent={() => (
          <View className="h-12 items-center justify-center w-full">
            <ListFetchingMoreFooter
              className="py-0"
              isFetchingNextPage={isFetchingNextPage}
            />
          </View>
        )}
      />
    </React.Fragment>
  );
};

seller.video.mp4

)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions