0

ReactJS - TypeError: Cannot read property '0' of undefined

this.ws.onmessage = e => {
  var tbox = JSON.parse(e.data);
  this.setState({
  user : this.state.usernames.concat(tbox.data[0].user),
  messages : this.state.messages.concat(tbox.data[0].message)
})
console.log(tbox.data[0].user + ': ' + tbox.data[0].html);

I'm trying to parse, setState and display data in realtime (in a Ant Design List component) from a public websocket api.

I managed to get thus far but if someone can better help me steer in the right direction, that would be much appreciated!


const URL = 'wss://www.bitmex.com/realtime?subscribe=chat:1'

const data = [
  {
    user: 'buythediplosers',
    message: 'im over here waiting for nothing lol',
    time: '4:20 AM', /*TODO: let the user set their timezone*/
  },
];


class Trollbox extends Component {
  constructor(props) {
    super(props);
    this.state = {
        usernames: [],
        messages: [],
        timestamps: [],
    }
  }

  ws = new WebSocket(URL)

  componentDidMount() {
    this.ws.onopen = () => {
      console.log('connected')
    }

    this.ws.onmessage = e => {
      var tbox = JSON.parse(e.data);
      this.setState({
        user : this.state.usernames.concat(tbox.data[0].user),
        messages : this.state.messages.concat(tbox.data[0].message)
      })
      console.log(tbox.data[0].user + ': ' + tbox.data[0].html);
    }

    this.ws.onclose = () => {
      console.log('disconnected')
      this.setState({
        ws: new WebSocket(URL),
      })
    }
  }

  render() {
    return (
      <div>
        <div>
          <List
            itemLayout="horizontal"
            dataSource={data}
            renderItem={item => (
              <List.Item>
                <List.Item.Meta
                  description={
                    <div>
                      <p>
                        <b>{item.user}</b>: {item.message} {item.time}
                      </p>
                    </div>
                  }
                />
              </List.Item>
            )}
          />
        </div>
...
console.log(tbox.data[0].user + ': ' + tbox.data[0].html);

shows me what I want to see in the console, which is a step forward for me: console output

   console.log(this.state.usernames + ': ' + this.state.messages);

though, this bunches it all up unlike the previous line while still giving me an error:

error message

EDIT: JSON sample:

{ 
   "table":"chat",
   "action":"insert",
   "keys":[ 
      "id"
   ],
   "data":[ 
      { 
         "channelID":1,
         "date":"2019-11-27T07:20:30.862Z",
         "fromBot":false,
         "html":"Keepitreal: ok bruh\n",
         "id":43087881,
         "message":"Keepitreal: ok bruh",
         "user":"cryxix"
      }
   ],
   "filterKey":"channelID"
}
3
  • Kindly post your json data sample. Commented Nov 27, 2019 at 7:19
  • @PrabhjotSinghKainth I edited the question! i.imgur.com/U8BCBsn.png Commented Nov 27, 2019 at 7:22
  • try to console tbox variable and see if it is returning data or not. Commented Nov 27, 2019 at 7:25

2 Answers 2

1

"this.ws.onmessage" handles every message from the other endpoint, so you have to make sure your code can handle every case that could happen.

first time json without tbox.data comes, tbox.data is undefined, so you have the error "Cannot read property '0' of undefined".

second time the error is "Cannot read property 'user' of undefined", so tbox.data is not undefined but tbox.data[0] is undefined. I think tbox.data is a empty array(data : []).

if you want to use tbox.data[0].user, check tbox.data[0] is not undefined.

try

if(tbox.data && tbox.data.length > 0){ .....}
Sign up to request clarification or add additional context in comments.

Comments

1

Looking at the images you provided in your comments, this one: errors Shows that the first 3 responses you are getting are different than the ones you are expecting, and don't have key called user in it, hence why you are getting that error. You can skip over it by adding a conditional like:

if(tbox.data){
      this.setState({
        user : this.state.usernames.concat(tbox.data[0].user),
        messages : this.state.messages.concat(tbox.data[0].message)
      })
}

In regards to your second question,

though, this bunches it all up unlike the previous line while still giving me an error:

This is because you are posting the entirety of your this.state.usernames which is repeatedly growing larger as an array. If you want to post it that way, you have to loop through the state and log each one separately.

1 Comment

Sorry, I made a typo, and tried to edit it before you saw it, it should read if(tbox.data) not tbox.user

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.