Henrik
Henrik

Reputation: 928

React Native JavaScript: TypeError: null is not an object (evaluating 'chatSocket.send')

So I have an React Native Project and I am using JavaScript WebSockets. When I try to send a payload to the websocket I get this error:

TypeError: null is not an object (evaluating 'chatSocket.send')

(The chatSocket is my webSocket)

import React, {useEffect, useState} from 'react';
import {
  Button,
  FlatList,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from 'react-native';

const Chat = ({route, navigation}) => {
  const { username, chatid } = route.params;


  useEffect(() => {
    setupWebSocket(chatid)
  }, [])



  var chatSocket = null;
  var roomId = null;
  
  function closeWebSocket(){
      if(chatSocket != null){
          chatSocket.close()
          chatSocket = null
      }
  }
  
  function setupWebSocket(room_id){
  
      console.log("setupWebSocket: " + room_id)
  
      roomId = room_id
  
      // close previous socket if one is open
      closeWebSocket()
  
  
      var ws_path = "ws://192.168.2.110:8000/chat/" + room_id + "/" + "?ec5ccab5d15ad8d6fd5e3f91cbfd8b6dac8fcf69";
  
      
      
      // console.log("Connecting to " + ws_path);
      chatSocket = new WebSocket(ws_path);
  
      // Handle incoming messages
      chatSocket.onmessage = function(message) {
          // Decode the JSON
          // console.log("Got chat websocket message " + message.data);
          console.log("Got websocket message.");
          var data = JSON.parse(message.data);
          // console.log(data)
  
          // display the progress bar?
          // displayChatroomLoadingSpinner(data.display_progress_bar)
  
          // Handle errors (ClientError)
          if (data.error) {
              console.error(data.error + ": " + data.message)
              return;
          }
          // Handle joining (Client perspective)
          if (data.join) {
              console.log("Joining room " + data.join);
          }
          // Handle leaving (client perspective)
          if (data.leave) {
              // do nothing
              console.log("Leaving room " + data.leave);
          }
          if (data.msg_type == 0) {
            appendChatMessage(data, true)
          }
      };
  
      chatSocket.addEventListener("open", function(e){
          console.log("ChatSocket OPEN")
          // join chat room get data from local database here
          if(1 == 1){
              chatSocket.send(JSON.stringify({
                  "command": "join",
                  "room": roomId,
              }));
          }
      })
  
      chatSocket.onclose = function(e) {
          console.log('Chat socket closed.');
      };
  
      chatSocket.onOpen = function(e){
          console.log("ChatSocket onOpen", e)
      }
  
      chatSocket.onerror = function(e){
          console.log('ChatSocket error', e)
      }
  
      if (chatSocket.readyState == WebSocket.OPEN) {
          console.log("ChatSocket OPEN")
      } else if (chatSocket.readyState == WebSocket.CONNECTING){
          console.log("ChatSocket connecting..")
      }
  }
 
  const appendChatMessage = (data, isNewMessage) => {

    var msg = data.message
    var timestamp = data.natural_timestamp
    var user_id = data.user_id
    var username = data.username


    logData(msg, timestamp, user_id, username, isNewMessage)
  }

  const [newChatMessage, setNewChatMessage] = useState({})
  // console.log(newChatMessage)

  const logData = (msg, timestamp, user_id, username, isNewMessage) => {
    if(isNewMessage){
      // console.log(msg)
      // console.log(username)
    }
    setNewChatMessage({...newChatMessage, 
      "message": msg,
      "username": username
    })
  };



  const [message, setMessage] = useState("")


  const handleSend = (messagex) => {
    chatSocket.send(JSON.stringify({
      "command": "send",
      "message": messagex,
      "room": "1"
    }));
  };

  return (
    <View>
      <Text style={{textAlign: "center", fontSize: 30}}>Chat</Text>
        <TextInput placeholder="Message" onChangeText={(value) => setMessage(value)} style={{borderRadius: 10, borderColor: "black", borderWidth: 2}}/>
        <Button title="Send" onPress={() => handleSend(message)} />
    </View>
  );
};

export default Chat;

I think there is an error with React Hooks 🤔

I will shortly explain the code:

The component is called from a Navigation App.Js. There is no error everything works fine. Than I setup the WebSocket on the frontend. It connects to an Ip with the Auth-Token in the domain (This isn't optimal, just for testing). Than if the user puts something in the <TextInput /> a useState() will be updated and if I than click on the button send the data should be sent.

So now comes the weird part: Sometimes it works and if I click on the button again with a delay of 1-60 seconds it won't work. :/

If you need more information please write a command. Maybe you had the error :)

Upvotes: 0

Views: 1268

Answers (1)

Kai
Kai

Reputation: 2599

The issue is that your chatSocket is getting defined as a plain variable in the body of the function component. Anything defined on a function component will be recreated every time the component is run/rendered, as it's just a function.

I would recommend wrapping the socket in a useRef to persist it between renders.

Something like const chatSocket = useRef(null);

and then in your setup function, initialize it with chatSocket.current = new WebSocket(ws_path);

Upvotes: 1

Related Questions