'problem with react native asyncstorage / giftedChat

I am trying to display messages saved in asyncstorage when a user is offline. I am able to store the new messages in asyncstorage, but I keep receiving the following errors: Warning: Failed %s type: %s%s, prop, Invalid prop messages of type object supplied to GiftedChat, expected an array. Warning: Failed %s type: %s%s, prop, Invalid prop messages of type object supplied to MessageContainer, expected an array., Invariant Violation: Tried to get frame for out of range index NaN

I'm unsing netInfo to check the online status, and if the user is online messages get retrieved from firebase (new messages get saved into asyncstorage for now). I've made a little trial with plain text in another project to see if I'm writing my functions correctly, and it does work fine..here i'm not sure how to change the object type for giftedChat, and what the other error means..what am I doing wrong? I've only got as far as getting only the last message saved in asyncstorage onto the console :/

This is my code

import React from "react";
import { View, Text, Platform, KeyboardAvoidingView } from "react-native";
import { GiftedChat, Bubble, InputToolbar } from "react-native-gifted-chat";
import { useState, useEffect, useCallback } from "react";
//using db reference and auth
import { db } from "../firebase/firebase-config";
//import of asyncstorage
import AsyncStorage from "@react-native-async-storage/async-storage";
//import of netinfo
import NetInfo from "@react-native-community/netinfo";
import {
  addDoc,
  collection,
  onSnapshot,
  query,
  orderBy,
} from "firebase/firestore";

export default function Chat(props) {
  //retrieving props
  let { name, bg, userId } = props.route.params;

  //reference to the database
  const myReference = collection(db, "messages");
  const [messages, setMessages] = useState([]);
  //connection state
  const [onlineState, setOnlineState] = useState();

  //save new messages locally via asyncstorage
  //setItem() is used both to add new data item (when no data for given key exists), and to modify existing item (when previous data for given key exists).
  const saveMessages = async (value) => {
    let messages = "";
    try {
      messages = JSON.stringify(value);
      await AsyncStorage.setItem("messages", messages);
      console.log("message saved in asyncstorage");
      console.log(await AsyncStorage.getItem("messages"));
    } catch (e) {
      // saving error
      console.log(error);
    }
  };

  //getMessages function to asynchronously retrieve messages from asyncstorage
  //reading data
  //getItem returns a promise that either resolves to stored value when data is found for given key, or returns null otherwise.
  const getMessages = async () => {
    try {
      const jsonValue = await AsyncStorage.getItem("messages");
     //error when setting the messages state
      setMessages(JSON.parse(jsonValue));
      console.log(JSON.parse(jsonValue));
    } catch (e) {
      // error reading value
      console.log(error);
    }
  };

  //async function to delete messages stored in asyncstorage
  const deleteMessages = async () => {
    try {
      await AsyncStorage.removeItem("messages");
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    let isMounted = true;
    props.navigation.setOptions({ title: name });

    //using netInfo to find out the user's connection status, and fetching messages from asyncstorage if they are offline (and from firestore if they are online)
    NetInfo.fetch().then((connection) => {
      if (connection.isConnected) {
        const messagesQuery = query(myReference, orderBy("createdAt", "desc"));
        //set the connection state to online
        setOnlineState(true);
        console.log("online");
        // onSnapshot returns an unsubscriber, listening for updates to the messages collection
        //if user is logged in and their collection is empty (default, users are anonymous and can't log back in)
        const unsubscribeList = onSnapshot(messagesQuery, onCollectionUpdate);
        // Delete previously saved messages in asyncStorage
        //deleteMessages();
        // Save messages to asyncStorage
        saveMessages();
        return () => {
          //unsubscribe to onSnapshot and auth
          isMounted = false;
          unsubscribeList();
        };
      } else {
        console.log("offline");
        //set the connection state to online
        setOnlineState(false);
        getMessages();
      }
    });
  }, []);

  const onCollectionUpdate = (snap) => {
    //setting the list
    setMessages(
      snap.docs.map((doc) => ({
        _id: doc.data()._id,
        createdAt: doc.data().createdAt.toDate(),
        text: doc.data().text,
        user: doc.data().user,
      }))
    );
  };

  const addMessage = (message) => {
    addDoc(myReference, {
      _id: message._id,
      text: message.text || "",
      createdAt: message.createdAt,
      user: message.user,
    })
      .then(() => {
        console.log("Doc created");
      })
      .catch((e) => console.log(e.message));
  };

  // Create custom onSend function, appending the newly created message to the messages state,
  // then calling addMessage to add to Firestore
  const onSend = useCallback((messages = []) => {
    setMessages((previousMessages) =>
      GiftedChat.append(previousMessages, messages)
    );
    saveMessages(messages[0]);
  }, []);

  /**  //this will allow to send new messages
  onSend(messages = []) {
    this.setState((previousState) => ({
      messages: GiftedChat.append(previousState.messages, messages),
    }));
  } */

  //this will allow to change the message bubble color
  const renderBubble = (props) => {
    return (
      <Bubble
        {...props}
        wrapperStyle={{
          right: {
            backgroundColor: "#000",
          },
        }}
        textProps={{
          style: {
            color: props.position === "left" ? "#000" : "#fff",
          },
        }}
      />
    );
  };

  //gifted chat feature - do not show the input box when the user is offline (so that they can't try to send messages offline)
  const renderInputToolbar = (props) => {
    if (!onlineState) {
      //hide toolbar
    } else {
      //display input box / toolbar
      return <InputToolbar {...props} />;
    }
  };

  return (
    <View style={{ flex: 1, backgroundColor: bg }}>
      <GiftedChat
        renderBubble={renderBubble.bind()}
        renderInputToolbar={renderInputToolbar.bind()}
        messages={messages}
        onSend={(messages) => onSend(messages)}
        showAvatarForEveryMessage={true}
        user={{
          _id: userId,
          name: name,
          avatar: "https://placeimg.com/140/140/any",
        }}
      />
      {/**to fix keyboard issue on old models of android */}
      {Platform.OS === "android" ? (
        <KeyboardAvoidingView behavior="height" />
      ) : null}
    </View>
  );
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source