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.