1. Agora, quando a gente envia a primeira mensagem, a gente pode ver que ela está bugada aqui, no lado errado e sem uma key única, vamos em messageList

    interface Props {
      messages: Messages[];
    }
    
    const MessagesList = ({ messages }: Props) => {
      const renderItem: ListRenderItem<Messages> = ({ item }) => (
        <MessageCard item={item} />
      );
    
    	return (
        <FlatList
          data={messages}
          inverted
          keyExtractor={(item, index) => item._id + index.toString()}
          renderItem={renderItem}
          showsVerticalScrollIndicator={false}
          contentContainerStyle={{ paddingTop: 20 }}
        />
      );
    
  2. Agora que estamos tipando certinho, vamos para o card e fazer a modificação lá, que estão incorretas

    interface Props {
      item: Messages;
    }
    
    const MessageCard = ({ item }: Props) => {
      const [senderId, setSenderId] = useState("");
    
      const handleGetUser = async () => {
        const user = await AsyncStorage.getItem("user");
        const { _id } = JSON.parse(user || "");
    
        setSenderId(_id);
      };
    
      useEffect(() => {
        handleGetUser();
      }, []);
    
      return (
        <>
          {item.sender === senderId ? (
            <SenderMsgContainer>
              <SenderMsg>{item.content}</SenderMsg>
            </SenderMsgContainer>
          ) : (
            <ReciverMsgContainer>
              <ReciverMsg>{item.content}</ReciverMsg>
            </ReciverMsgContainer>
          )}
        </>
      );
    };
    
  3. Antes de irmos pegar todos os chats, vamos primeiro tipar tudo dentro de messages

    import { Product, Seller } from "./Product";
    
    export interface Messages {
      _id?: string;
      content: string;
      receiver: string;
      sender: string;
    }
    
    export interface Buyer {
      _id: string;
      email: string;
      name: string;
      phone: string;
    }
    
    export interface Chats {
      _id: string;
      buyer: Buyer;
      messages: Messages[];
      product: Product;
      seller: Seller;
      updatedAt: string;
    }
    
  4. Desse jeito agora temos tudo certo aqui nos chats, vamos então pegar todos os chats para exibir em allChats. Iremos para dentro de ChatList, que está dentro de components, com isso feito, nós vamos em ChatList, que é o componente que exibe para os usuários os chats que temos, e aqui vamos modificar algumas coisas

    const ChatList = () => {
      const [loading, setLoading] = useState(true);
      const [chats, setChats] = useState<Chats[]>([]);
    
      const renderItem: ListRenderItem<Chats> = ({ item }) => (
        <ChatCard data={item} />
      );
    
      const handleGetChats = async () => {
        const res = await chatService.getChats();
    
        setChats(res.data);
    
        setLoading(false);
      };
    
      useFocusEffect(
        React.useCallback(() => {
          handleGetChats();
        }, [])
      );
    
      if (loading) {
        return <Loader />;
      }
    
      return (
        <>
          {chats.length <= 0 ? (
            <NoChat>Você não tem chats no momento</NoChat>
          ) : (
            <FlatList
              data={chats}
              keyExtractor={(item) => item._id}
              renderItem={renderItem}
              showsVerticalScrollIndicator={false}
              contentContainerStyle={{ paddingBottom: 80 }}
            />
          )}
        </>
      );
    };
    
  5. E agora conhecendo o useFocus, vamos usar ele também na home, para que todas as vezes que a gente acesse ela, se tiver algum produto novo ele vai aparecer

    useFocusEffect(
       React.useCallback(() => {
        handleGetProducts();
      }, [])
    );
    
  6. Agora que a gente já tem a estrutura pronta, vamos para o card, que é o mais importante de fato

    interface Props {
      data: Chats;
    }
    
    const ChatCard = ({ data }: Props) => {
      const navigation = useNavigation<PropsStack>();
    
      return (
        <Container
          activeOpacity={0.85}
          onPress={() => {
            navigation.navigate("Chat", {
              product: data.product,
              sellerName: data.seller.name,
              sellerId: data.seller._id,
              messages: data.messages,
            });
          }}
        >
          <Image source={{ uri: data.product.images[0].url }} />
          <InfoContainer>
            <Price>R$ {data.product.price}</Price>
            <Title numberOfLines={2}>{data.product.name}</Title>
            <LikeContainer>
              <SellerContainer>
                <PublishedText>
                  Publicado em {getDate(data.product.createdAt)} por:
                </PublishedText>
                <SellerName>{data.seller.name}</SellerName>
              </SellerContainer>
              <TrashButton onPress={() => {}} activeOpacity={0.85}>
                <TrashImage source={trashIcon} />
              </TrashButton>
            </LikeContainer>
          </InfoContainer>
        </Container>
      );
    };
    
  7. Agora, já conseguimos navegar livremente para dentro do nosso chat

  8. Vamos então buscar enviar mensagens aqui dentro do chat, isso lá em Chat. Vamos começar instalando as dependências do socketio, que será a lib que usaremos para começar isso

    npm install socket.io-client
    
  9. Agora, nós podemos fazer a conexão com o socket

    let socket: Socket | null = null;
    
    const connectSocket = async () => {
      const token = await SecureStore.getItemAsync("onebitshop-token");
    
      socket = io("ws://192.168.0.10:3000", {
        auth: {
          token: token,
        },
      });
    };
    
    connectSocket();
    
    const Chat = ({ route }: Props) => {
    
  10. Com ele conectado, podemos criar a estrutura que vai fazer a manipulação das mensagens

    const Chat = ({ route }: Props) => {	
    	const [content, setContent] = useState("");
      const [receiver, setReceiver] = useState("");
      const [sender, setSender] = useState("");
      const [messageList, setMessageList] = useState<Messages[]>([]);
    
      const handleGetUsers = async () => {
        const user = await AsyncStorage.getItem("user");
        const { _id } = JSON.parse(user || "");
    
        if (route.params.buyerId === _id) {
          setSender(route.params.buyerId);
          setReceiver(route.params.sellerId);
        } else {
          setSender(route.params.sellerId);
          setReceiver(route.params.buyerId);
        }
      };
    
      const handleSendMessage = async () => {
        const message = {
          content,
          receiver,
          sender,
        };
    
        const conversationId = route.params._id;
    
        socket?.emit("message_sent", {
          conversationId,
          message,
        });
    
        setContent("");
      };
    
      useEffect(() => {
        setMessageList(route.params.messages);
        handleGetUsers();
      }, []);
    
      useEffect(() => {
        socket?.on("new_message", (newMessage: any) => {
          console.log(newMessage.message);
          setMessageList((mostRecentState) => [
            newMessage.message,
            ...mostRecentState,
          ]);
        });
    
        return () => {
          socket?.off("new_message");
        };
      }, [socket]);
    
  11. E agora podemos usar tudo que a gente criou

    return (
      <Container>
        <ChatHeader
          sellerName={route.params.sellerName}
          sellerId={route.params.sellerId}
          product={route.params.product}
        />
    
        <MessagesList messages={messageList} />
    
        <InputContainer>
          <Input
            placeholder="Digite sua mensagem"
            placeholderTextColor="white"
            multiline
            value={content}
            onChangeText={(val) => {
              setContent(val);
            }}
          />
          <SendButton onPress={handleSendMessage}>
            <SendIcon source={chatImage} />
          </SendButton>
        </InputContainer>
    
        <NavBar />
      </Container>
    );
    
  12. E agora sempre que enviarmos uma mensagem, poderemos ver ela aqui atualizando no chat