I just finishing setting up my socket in my react native and nodejs project and still my flatlist does not update instantly when a message is sent, i need to refresh the app in order for it to update.
I thought that by using socket this will work but still it is not working. whenever i user opens a chat i get eg. user: 1 has joined conversation 1 in the console which indicates that the socket is working.
Client Side
function ChatScreen({route,navigation}) { const message = route.params.message; const [messages, setMessages] = useState(message.Messages); const [text, setText] = useState(''); const [socket, setSocket] = useState(null); const { user } = useAuth(); const index = route.params.index; const updateView = route.params.updateView; useEffect(() => { const newsocket =io.connect(socketURL) setMessages(messages); newsocket.on('connect', msg => { console.log(`user: ${user.id} has joined conversation ${message.id}`) setMessages(messages=>messages.concat(msg)) setSocket(newsocket) }); 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); } return ( <FlatList inverted data={message.Messages} keyExtractor={(message) => message.id.toString()} renderItem={({item,index})=>( <> <Text> {moment(item.createdAt).fromNow()} </Text> <MessageBubble text={item.message} mine={item.senderId !== user.id} /> </> )} /> <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)}}> </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.join(data.ConversationId); io.sockets.in(data.to).emit('send_message', { message: data.message, to: data.to }); }); });
UPDATE
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("http://192.168.1.103:9000") newsocket.on('connect', msg => { console.log(`user: ${user.id} has joined conversation ${message.id}`) setSocket(newsocket) setMessages(message.Messages) }); newsocket.on("send_message", (msg) => { console.log("this is the chat message:", msg); setMessages([ { ...message.Messages },...messages]); }); return()=>newsocket.close; }, []); const onSend = (ConversationId,senderId,receiverId,message) => { console.log("sent") 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={(message) => message.id.toString()} 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
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 }) }); });
Using the updated code, when i open a chat i get
user: 43 has joined conversation 4 ---- on client side console connected ---- on server side console
Using the updated code, when i send a message i get
this is the chat message: Object { "conversationId": 25, "message": "You", "receiverId": 47, "senderId": 43, } --- in my client side console { to: 47, from: 43, message: 'You', ConversationId: 25 } ---- server side console
But then i get an error
undefined is not an object (evaluating 'message.id.toString')
I think my problem is that i am not emitting the the message id correctly and therefore my flatlist does not know it. To get a message id, i need to store the message in db first
NEW UPDATE
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) newsocket.on('connect', msg => { console.log(`user: ${user.id} has joined conversation ${message.id}`) setSocket(newsocket) setMessages(message.Messages) }); newsocket.on("send_message", (msg) => { console.log("this is the chat message:", msg); const data = [...messages]; console.log(data) data.push(msg); setMessages(data); }); return(()=>newsocket.close()); }, []); const onSend = (ConversationId,senderId,receiverId,message) => { console.log("sent") 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()} 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
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 }) }); });
Now using the new updated code when i send a message only the new message gets rendered to the sender without the previous messages, and the receiver does not receive anything while on the chat.
https://stackoverflow.com/questions/65325432/react-native-flatlist-does-not-update-instantly-when-i-send-a-message December 16, 2020 at 10:40PM
没有评论:
发表评论