0

I am working on a Chat Room portion of a larger React Native app and am facing issues with the updating of the page after a text has been sent. Currently, when the user compiles a text in a TextInput and hits the send button, it triggers a mutation that is supposed to add a message object to the chatroom model, which is linked to all of the users that are currently in the chatroom. It is then supposed to take the result from this mutation, which is the updated chatroom connected to all the users (the current user included obviously) and render its contents. It is intended to rerender the page after the activeThread atom is updated, since the page used the contents of activeThread to render everything on the page, new messages included. However, this occurs asyncronously and it tries to render a promise.... which you can't do. I've tried everything I'm capable of, using thens and awaits everywhere I could but JavaScript's giving me the middle finger pretty hard on this one. My code is below...

const handleSendMessage = async () => {
        console.log(activeThread.id)
        if (newMessage.length > 0){
             return sendMessage({
                variables: {
                    chatroomId: activeThread.id,
                    content: newMessage
                }
            }).then( async (newMessageThread) => {
                await setUpdating(true)
                await setNewMessage("")
                await setKeyboardVisible(false);
                await setActiveThread(newMessageThread)
            }).then( async() => {
                await console.log(activeThread)
                await setUpdating(false)
            })
        }
        else{
        }
    }

setUpdating is part of a useState. This is defaulted to false and when true the main page is not set to render. It is intended as a guard against attempting to render the promise. Didn't work, obviously

setNewMessage is defaulted to "" and is responsible for keeping track of the text the user has entered into the TextInput. Pretty irrelevant here.

setKeyBoardVisible is pretty self explanatory and also not necessary

setActiveThread is the heavy lifter here. Pretty much all of the contents rendered are going to be pulling data from activeThread, which is, again; a recoil state. For example, everything below looks essentially something like

<View>
    <Text> {activeThread.someMethodOrValue} </Text>
</View>

I can only assume this has something to do with the async-ing. I have a console.log(error) statement in my backend GraphQL mutation resolver that would catch any errors there, and it's not triggering anything. The error I get everytime is the following...

TypeError: undefined is not an object (evaluating 'activeThread.chatroomName.split')

This error is located at:
    in MessageThread (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in {/* keeps going down the stack you get the idea */}

[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'activeThread.chatroomName.split')]
at Pages/CommunicationPage/MessageThread.js:210:37 in MessageThread

Any solutions?

1 Answers1

0

While the code I had still looks like it should work to me, we all know how finnicky code can be sometimes. What ended up working was separating the handleSendMessage function and the mutation, creating a whole new function for the mutation.

My new code looks like this...

const handleSendMessage = () => {
        if (newMessage.length > 0){
             handleMutation().then( (resolved) => { // This line fixed all the promise issues
                setNewMessage("") // clears current message input
                let newActiveThread = resolved.data.driverSendMessage.chatroom // creates new thread JSON from mutation data
                console.log(newActiveThread) // testing out a different bug now lolllll
                setActiveThread(newActiveThread) // Sets current thread to match the new one

                // changes the entire user state, leaving all over threads untouched but updating the current one
                let updatedThreads = [newActiveThread]
                user.chatrooms.forEach( (chat) => {
                    if (chat.id == newActiveThread.id){
                        console.log("Skipping " + newActiveThread.chatroomName)
                    }
                    else {
                        updatedThreads.push(chat)
                    }
                })

                // changes the main recoil state
                setUser({...user, chatrooms: updatedThreads})
            })
        }
        else{
            // Throw Error Handling for no input or just do nothing, we'll see
        }
    }

    const handleMutation = async () => {
        return sendMessage({
            variables: {
                chatroomId: activeThread.id,
                content: newMessage
            }
        })
    }
Peter Csala
  • 17,736
  • 16
  • 35
  • 75