React hooks + Firebase state value after POST request does not display until hard refresh

Viewed 61

So after every POST request, only composerName and message field are correctly displayed (don't want sorter node to be displayed) and the timestamp is not. When I console.log the data, everything is there. No error or warnings. I can also see everything in their place after a hard refresh of the page.

Also, when I type something into input text area, onChange seems to trigger re-render of the component after each keystroke, and then I can see the timestamp being displayed and even updated. Maybe I'm using useEffect hooks in a wrong way? I assume this is the issue but I can't move any further from here.

Chatroom.js before return jsx:

// import statements

const Chatroom = ({ match }) => {
  // ...
  const [messages, setMessages] = useState([])
  const [message, setMessage] = useState('')
  // ...

  useEffect(() => {

    let messagesRef = db
      .ref(`REFERENCE`)
      .orderByChild('sorter')
      .limitToFirst(numOfMessagesPerLoad)

    setMessagesLoading(true)

    messagesRef.on('value', snapshot => {
      const messagesList = []

      snapshot.forEach(data => {
        messagesList.push(data.val())
      })

      setMessages(messagesList)
      setMessagesLoading(false)
    })

    return () => messagesRef.off()
  }, [])

  // ...

  const postMessageHandler = async e => {
    e.preventDefault()
    setPosting(true)

    try {
      const newMessage = {
        composerName:
          'Name ' + Math.floor(Math.random() * 100).toString(), // just to make each composerName unique
        creationTime: Date.now(),
        sorter: Date.now() * -1,
        message,
      }
      const res = await axios.post(`ENDPOINT`, newMessage)

      setMessages([res.data.data.message, ...messages])
      setMessage('')
      setPosting(false)
    } catch (error) {
      console.error(error.message)
    }
  }

Chatroom.js return jsx:

  return (
    <>
      <section className="main-comments">
        <div className="main-comments-top">
          // ...

          <div className="comment-form">
            <Form className="comment-send-form" onSubmit={postMessageHandler}>
              <input
                type="text"
                name="text"
                value={message}
                placeholder="Say something..."
                className="comment-form-input"
                onChange={e => setMessage(e.target.value)}
              />

              <Button
                className="msg-send-button"
                type="submit"
                disabled={message.length === 0}
              >
                {posting ? (
                  <ClipLoader size={20} color="#8585ff" />
                ) : (
                  <span>Post</span>
                )}
              </Button>
            </Form>
          </div>
        </div>

          // ...

        <div id="comments" className="comments">
          <div className="comments-area">
            {messages.length === 0 && !messagesLoading ? (
              <div style={{ textAlign: 'center' }}>
                <p>This feed has no messages yet.</p>
              </div>
            ) : (
              messages
                .sort((a, b) => {
                  return a.sorter - b.sorter
                })
                .map(msg => (
                  <div className="com-each-comment" key={msg.creationTime}>
                    <div className="user-and-comment">
                      <p className="username-display">
                        <span>{msg.composerName}</span>
                      </p>
                      <p className="com-text-comment">{msg.message}</p>
                    </div>

                    <div className="comment-footer">
                      <small className="comment-timestamp">
                        {timeSince(msg.creationTime)} // this is not being displayed until hard refresh
                        // timeSince() is just a custom function that I wrote to change timestamp format
                      </small>
                    </div>
                  </div>
                ))
            )}
          </div>
        </div>
      </section>
    </>
  )
}

export default Chatroom

Thank you

More Info: When tested through postman, things work and get displayed just as expected

0 Answers
Related