Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Socket.io data spamming the console until the Payload is too large

The following code is part of a chat application build with react native which is working via a socket.io server.

const Message = ({text, isSent}) => {
  return (
    <View style={[styles.messageContainer, isSent ? styles.sentMessage : styles.receivedMessage]}>
      <Text style={styles.messageText}>{text}</Text>
    </View>
  )
}

export const ChatScreen = ({ route }) => {

  const {control, handleSubmit, reset} = useForm();
  const socket = useContext(SocketContext)
  const { user } = route.params;

  const onSendPress = async(data) => {

    const message = data.messageInput
    const uuid = await AsyncStorage.getItem('uuid')


    if(message === '') return

    console.log('Message Send: ' + message + ' | to: ' + user.uuid)
    addMessage(message, true);
    reset();

    socket.emit('send-chat-message', {
      message: message,
      sender: uuid,
      recipient: user.uuid
    })

  }

  socket.on('receive-chat-message', async(data) => {
    console.log(data)

    if(data.sender !== user.uuid) return

    addMessage(data.message, false)

  })

  const [messages, setMessages] = useState([
    { text: 'Hello! How can I help you today?', isSent: false },
    { text: 'Hi! I was wondering if you could give me some advice.', isSent: true },
    { text: 'Of course! I would be happy to help.', isSent: false },
  ]);

  const scrollViewRef = useRef(null);

  const addMessage = (text, isSent) => {
    setMessages([...messages, { text, isSent }]);

    scrollViewRef.current.scrollToEnd({ animated: true });
  };


  return (
    <View style={styles.background}>

      <StatusBar style="auto" />

      <ScrollView style={styles.container} ref={scrollViewRef}>
        {messages.map((message, index) => (
          <Message key={index} text={message.text} isSent={message.isSent} />
        ))}
      </ScrollView>

      <KeyboardAvoidingView behavior='padding' keyboardVerticalOffset={55} style={styles.bottomTextInput}>

        <Controller
          name={'messageInput'}
          control={control}
          render={({field: {value = '', onChange, onBlur}}) => (
            <>
              <View style={styles.input}>
                <TextInput 
                  style={{paddingHorizontal: 11, paddingTop: 2}}
                  onChangeText={onChange}
                  onBlur={onBlur}
                  value={value}
                  multiline={true}
                  fontSize={17}
                />
              </View>

              <TouchableOpacity onPress={handleSubmit(onSendPress)} style={[styles.sendInput, { backgroundColor: value === '' ? '#cacaca' : '#858AE3'}]}>
                <Ionicons 
                  name={'paper-plane'} 
                  size={20} 
                  color={'white'} />
              </TouchableOpacity>
            </>
          )}
        />

      </KeyboardAvoidingView>

    </View>
  )
}

Now everything is working quite well, the only problem I’m running into is that somehow the data I receive with the receive-chat-message event is doubling each time a new message comes in. To make it visual, this is my console after three different messages:

{"message": "First Message", "recipient": "7fa68f52-ad00-4bdd-9cfc-2af2e15d8d8d", "sender": "2bfe33f0-4882-4ff6-a9ac-4356cd3e7a66"} 
{"message": "Second Message", "recipient": "7fa68f52-ad00-4bdd-9cfc-2af2e15d8d8d", "sender": "2bfe33f0-4882-4ff6-a9ac-4356cd3e7a66"} 
{"message": "Second Message", "recipient": "7fa68f52-ad00-4bdd-9cfc-2af2e15d8d8d", "sender": "2bfe33f0-4882-4ff6-a9ac-4356cd3e7a66"} 
{"message": "Third Message", "recipient": "7fa68f52-ad00-4bdd-9cfc-2af2e15d8d8d", "sender": "2bfe33f0-4882-4ff6-a9ac-4356cd3e7a66"} 
{"message": "Third Message", "recipient": "7fa68f52-ad00-4bdd-9cfc-2af2e15d8d8d", "sender": "2bfe33f0-4882-4ff6-a9ac-4356cd3e7a66"} 
{"message": "Third Message", "recipient": "7fa68f52-ad00-4bdd-9cfc-2af2e15d8d8d", "sender": "2bfe33f0-4882-4ff6-a9ac-4356cd3e7a66"} 
{"message": "Third Message", "recipient": "7fa68f52-ad00-4bdd-9cfc-2af2e15d8d8d", "sender": "2bfe33f0-4882-4ff6-a9ac-4356cd3e7a66"}

I checked if the server is really just getting one request at a time and it is like this. The server is only getting one request and is also only emitting one request to the client who is receiving the message.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I appreciate any help since the problem is literally bugging me out.

>Solution :

Most likely error is due to you are calling socket.on('receive-chat-message', ...) directly in component body, that means that every time component is rerendered – this line is executed, so you have multiple listeners in same component executing same code on this event, as you can see – every time you call setMessages – component is rerendered, additional listener is added and you are getting 1 more duplicate.

Solution: Wrap it with useEffect:

useEffect(() => {
  if (!user?.uuid) return;

  const fn = async (data) => {
    console.log(data);
    if (data.sender !== user.uuid) return;
    addMessage(data.message, false);
  };

  socket.on("receive-chat-message", fn);

  return () => {
    socket.off("receive-chat-message", fn);
  };
}, [socket, user?.uuid]);

Possible error #2 – setMessages([...messages, { text, isSent }]);. Here you can get errors due to closures, prefered to use functional state setter:

setMessages(messages => [...messages, { text, isSent }]);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading