【问题标题】:Socket.io data spamming the console until the Payload is too largeSocket.io 数据向控制台发送垃圾邮件,直到有效负载太大
【发布时间】:2023-02-01 01:17:33
【问题描述】:

以下代码是使用 react native 构建的聊天应用程序的一部分,该应用程序通过 socket.io 服务器运行。

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>
  )
}

现在一切都运行良好,我遇到的唯一问题是每次收到新消息时,我通过 receive-chat-message 事件收到的数据都会翻倍。为了使其可视化,这是我在三个不同的控制台之后消息:

{"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"}

我检查了服务器是否真的一次只收到一个请求,它是这样的。服务器只收到一个请求,也只向接收消息的客户端发送一个请求。

感谢您提供的任何帮助,因为这个问题确实困扰着我。

【问题讨论】:

    标签: javascript reactjs react-native socket.io


    【解决方案1】:

    最有可能的错误是由于您直接在组件主体中调用socket.on('receive-chat-message', ...),这意味着每次重新渲染组件时 - 执行此行,因此您在同一组件中有多个侦听器对此事件执行相同的代码,如您所见- 每次你调用setMessages - 组件被重新渲染,额外的监听器被添加,你又得到 1 个重复的。

    解决方法:用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]);
    

    可能的错误 #2 - setMessages([...messages, { text, isSent }]);。在这里你可以得到由于闭包而导致的错误,首选使用功能状态设置器:

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

    【讨论】:

      猜你喜欢
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 2014-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多