1

i am trying to implement a 1-1 private messaging feature inside my app, where 2 users can exchange messages live if they are both on the chat screen at the same time and if not the messages get stored in my postgres database and when the user opens the chat again they are loaded.

Currently with my code, when both users chat are open, when i try sending a message, the message does not get sent live i need to refresh the app in order for the chat to update. I think my socket is working since my console logs are getting returned in both frontend and backend consoles.

my problem is how to make the messages live and update my flatlist correctly(ie. the new messages appear at the bottom of my inverted list)?

Here is my code:

Client Side

  const message = route.params.message;
  const [messages, setMessages] = useState([]);
  const [text, setText] = useState('');
  const [socket, setSocket] = useState(null);
  const { user } = useAuth();

  useEffect(() => {
  const newsocket =io.connect(socketURL)
  setMessages(message.Messages)
  newsocket.on('connect', msg => {
  console.log(`user: ${user.id} has joined conversation ${message.id}`)
  setSocket(newsocket)
  });

  newsocket.on("send_message", (msg) => {
  console.log("this is the chat message:", msg);
  const data = [...messages]; 
  data.push(msg);
  setMessages(data); 
  });

  return(()=>newsocket.close());
  }, []);

  const onSend = (ConversationId,senderId,receiverId,message) => {
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
setText("")
const to = (user.id===route.params.message.user1? 
route.params.message.user2:route.params.message.user1)
    socket.emit(
    'message', { to: to, from: user.id, message,ConversationId });
  };

 const updateText=(text)=>{
 setText(text);
 }

<FlatList
    inverted
    data={messages}
    keyExtractor={(item,index)=>index.toString()}
    extraData={messages}
    renderItem={({item,index})=>(
        <>
        <Text>
         {moment(item.createdAt).fromNow()}
         </Text>
        <MessageBubble
        text={item.message}
        mine={item.senderId !== user.id}
        />
         </>
    )}   
    bounces={false}  
    />
    <View style={styles.messageBoxContainer}>
        <TextInput 
        onChangeText={updateText} 
        value={text} 
        />
        <TouchableOpacity 
         onPress={()=>{
         onSend(
         message.id,
         user.id, 
         (user.id===message.user1?message.user2:message.user1),
         text
         )}}
         >
         <Text>Send</Text>
        </TouchableOpacity>
     </View>

Server Side

const express = require("express");
const app = express();
const http = require("http");
const socket = require("socket.io")
const server=http.createServer(app);
const io =socket(server)

io.on('connection', (socket) => {
console.log("connected")
socket.on('message', (data) => {
console.log(data)
socket.emit('send_message', { message: data.message, receiverId: 
data.to,senderId:data.from,conversationId:data.ConversationId })
});
});

Thank you in advance, i have been trying to solve this problem for weeks and couldnt. Would really appreciate any help.

kd12345
  • 689
  • 10
  • 29

1 Answers1

0

after many attempts i managed to get it working thanks to Srikanth's answer on this Creating a private chat between a key using a node.js and socket.io.

CLIENT

useEffect(() => {
const newsocket =io.connect("http://192.168.1.103:9000")
setMessages(message.Messages)

newsocket.on('connect', msg => {
    console.log(`user: ${user.id} has joined conversation ${message.id}`)
    setSocket(newsocket)
    newsocket.emit('subscribe', message.id);
 });

newsocket.on("send_message", (msg) => {
    console.log("this is the chat messages:", msg);
    setMessages(messages => messages.concat(msg))
  });
 
 return(()=>newsocket.close());

 }, []);

const onSend = (ConversationId,senderId,receiverId,message) => {
console.log("sent")
const to = (user.id===route.params.message.user1? 
route.params.message.user2:route.params.message.user1)
socket.emit('message', { to: to, from: user.id, message,ConversationId });
setText("")
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
};

SERVER

io.on('connection',(socket)=>{
console.log('User '+socket.id+' connected')

socket.on('subscribe', (room)=> {
console.log('joining room', room);
socket.join(room);
});

socket.on('message', (data) => {
console.log(data)
console.log('sending room post',data.ConversationId)
io.sockets.in(data.ConversationId).emit('send_message', { message: 
data.message, receiverId: 
data.to,senderId:data.from,conversationId:data.ConversationId });
})
})

I have read many comments that suggested not to use rooms in 1-1 private messaging but this was the only possible way of getting it to work.

kd12345
  • 689
  • 10
  • 29