i am trying to pass my newsocket variable from my MessagesScreen.js to my ChatScreen.js.
I have been stuck on this point for a while and would appreciate any help possible. What i am trying to achieve is that only one connection gets emitted which i can listen to events on both screen.
The connection is now opened on the messagesScreen. My problem now is if user 1 is on the allmessages screen and user 2 is inside the chat. And user 2 sends user 1 a message, user 1's screen does not automatically update with the last message for the conversation the message was sent to, I need to either scroll to refresh or navigate from one page to the other in order for it to appear.
Here is my code:
PARENT --> messagesScreen.js
function MessagesScreen({navigation}) {
const [posts, setPosts] = useState([]);
const { user } = useAuth();
const [socket, setSocket] = useState(null);
const loadposts = async () => {
const response = await messagesApi.getMessages();// here i am loading all the conversation this user has
setPosts(response.data)
};
useEffect(() => {
newsocket = sockets(user.id); // newsocket is what i am trying to pass to child component
setSocket(newsocket);
loadPosts()
newsocket.on("send_message", (msg) => {
console.log("messages:", msg);
})
}, []);
return (
<FlatList
data={posts}
keyExtractor={(post) => post.id.toString()}
renderItem={({ item,index }) => (
<MessagesList
title={item.Post.title}
subTitle={item.Messages[0].message}
onPress={() => navigation.navigate(
routes.CHAT,{message:item,index,newsocket:socket})}
/>
)}
/>
)
CHILD ---> chatScreen.js
function ChatScreen({route,navigation,socket}) {
const [messages, setMessages] = useState([]);
const { user } = useAuth();
const index = route.params.index;
const message = route.params.message;
const newsocket = route.params.newsocket;
const loadListings = async () => {
const response = await messagesApi.getConversation(message.id);// here i am loading the messages in that specific conversation
setMessages(response.data.Messages)
};
useEffect(() => {
loadListings()
newsocket.emit('subscribe', message.id);
newsocket.on("send_message", (msg) => {
console.log("this is the chat messages:", msg);
setMessages(messages => [msg, ...messages]);
});
}, []);
const onSend = (ConversationId,senderId,receiverId,message) => {
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});
messagesApi.sendMessage({ConversationId,senderId,receiverId,message});
};
return(
<FlatList
inverted
data={messages}
keyExtractor={(item,index)=>index.toString()}
extraData={messages} // add this
renderItem={({item,index})=>(
<MessageBubble
text={item.message}
mine={item.senderId !== user.id}
/>
)}
/>
)
socket.js
import io from 'socket.io-client';
const newsocket = (user) => {
let newsocket = io.connect("http://192.168.1.107:9000")
newsocket.on('connect', msg => {
console.log(`waiting for user: ${user} to join a conversation`)
});
newsocket.emit('waiting', user);
return newsocket;
}
export default newsocket;
I would approach this differently.
Quick rough:
// socket-server.ts
import io from 'socket.io-client';
let socket: SocketIOClient.Socket = null;
export const getSocketServer = (): Promise<SocketIOClient.Socket> => {
return new Promise<SocketIOClient.Socket>(resolve => {
if (socket) {
console.info(`returning existing socket: ${socket.id}`);
return resolve(socket);
}
socket = io('http://localhost:4000', {
autoConnect: false,
});
socket.on('connect_error', (err) => {
console.error(err);
})
socket.on('connect', () => {
console.info(`creating new socket: ${socket.id}`);
return resolve(socket);
});
socket.open();
})
}
// then in your relevant modules
// module-a.ts
import React, {useEffect, useState} from 'react';
import {getSocketServer} from './../components/socket-server';
const Component = () => {
useEffect(() => {
const connect = async () => {
const socket = await getSocketServer();
socket.on('hello', (message) => {
console.info('hello from module A', message);
});
}
connect();
}, []);
return (
<>
<h2>Module A</h2>
</>
)
}
export default Component;
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
On the MessagesScreen
screen you are passing the SOCKET
function and not the variable it self. i think you do not need the function. you directly pass the variable and access in chatScreen
screen.
MessagesScreen.js
routes.CHAT,{message:item,index,updateView, newsocket})}
chatScreen.js
const newsocket = route.params.newsocket;
....
newsocket.emit('subscribe', message.id); // call like this
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.