Home > database >  react setting state in useeffect then trying to find something inside that state
react setting state in useeffect then trying to find something inside that state

Time:10-12

I am trying to create an in-app chat but i keep stumbling across the same problem in javascript. Inside my useEffect, i make an api call to my backend to GET all the conversations with all the messages included and set that to my records state. Also in my useEffect i have a socket listener that listens to the messages sent inside the chats and would like to update the the last message preview to the new message.

My problem is when i first load the web app and try sending a message i keep getting

TypeError: Cannot read properties of undefined (reading 'Messages')

Here is my code:


useEffect(()=> {
            axios
            .get('/api/messages/',{headers:{"auth-token":localStorage.getItem('jwtToken')}})
                .then(res => {
                    setRecords(res.data)
                })
                .catch(err =>
                    console.log(err)      
                )

    // main socket       
    const newsocket =io.connect(CONNECTION_PORT)

      newsocket.on('connect', msg => {
          setSocket(newsocket)
          console.log(`Admin ${ADMIN.id} is waiting. socketID: ${newsocket.id}`)
       });

        newsocket.emit('waiting', ADMIN.id);

        newsocket.on("socketListening", (msg) => {
            console.log(msg)
        
            try{
                    const result = records.find(e=>e.id===msg.conversationId) //Error occurs here
                    console.log(result)
                    const resultMessages=result.Messages;      
                    const newMessages =[msg,...resultMessages]
                    result.Messages=newMessages;
                    result.lastMessage=msg.message;
                    if(msg.senderId!==ADMIN.id){
                        result.Recipient=false;
                      }else{
                        result.Recipient=true;

                      }
                    console.log(result);
                    const arraywithoutrecord = records.filter(e=>e.id!==msg.conversationId)
                    setRecords([result,...arraywithoutrecord])
            }catch(e){
                console.log(e)
            }
        })

       return(()=>newsocket.close());

    },[]);

CodePudding user response:

Seems like creating a useEffect that subscribes to your "records" state would do the job.

Setting a state in react can be seen as a async function, thus why you get an undefined error

import { useEffect, useState } from 'react';
import axios from 'axios';

const Component = () => {

  const [records, setRecords] = useState(null);
  const [socket, setSocket] = useState(null);

  const CONNECTION_PORT = 1234;

  let myMsg;
  const newsocket = io.connect(CONNECTION_PORT);

  // First useEffect (called on init) :
  useEffect(() => {
    axios
      .get('/api/messages/', { headers: { 'auth-token': localStorage.getItem('jwtToken') } })
      .then(res => {
        setRecords(res.data);
      })
      .catch(err =>
        console.log(err)
      );

    // main socket
    

    newsocket.on('connect', msg => {

      // Set to component variable
      myMsg = msg;

      setSocket(newsocket);
      console.log(`Admin ${ADMIN.id} is waiting. socketID: ${newsocket.id}`);
    });

    newsocket.emit('waiting', ADMIN.id);

    newsocket.on('socketListening', (msg) => {
      console.log(msg);
    }, []);

    // Second useEffect (called every time "records" state is updated):

    useEffect(() => {


      try {

        const result = records.find(e => e.id === myMsg['conversationId']); //Error occurs here
        console.log(result);
        const resultMessages = result.Messages;
        const newMessages = [myMsg, ...resultMessages];
        result.Messages = newMessages;
        result.lastMessage = myMsg.message;

        if (myMsg['senderId'] !== ADMIN.id) {
          result.Recipient = false;
        } else {
          result.Recipient = true;
        }

        const arraywithoutrecord = records.filter(e => e.id !== myMsg['conversationId']);
        setRecords([result, ...arraywithoutrecord]);
      } catch (e) {
        console.error(e);
      }
    });

    return (() => newsocket.close());

  }, [records]);


  return (
    <></>
  );

};

CodePudding user response:

records does not contain the message your are looking for. Probably it is because data are not loaded yet.

try set logs and check: what is executing first: thenLog or socketListeningLog?

.then(res => {
    console.log("getting is done");
    setRecords(res.data)
})
  • Related