2

I'm currently trying to wrap my head around how a typical data structure would be implemented in React. Using a queue as an example, from what I understand, if I created it in Java, I could just define the function in this Javascript-translated format:

class Queue extends Component {

  constructor(props) {
    super(props);
    this.state = {message: "Test"}
  }

  queue(el) {
    let arr = this.state.arr.slice();
    arr.push(el);
    return arr;
  }

  dequeue = (el) => {
    let arr = this.state.arr.slice(1, this.state.arr.length);
    return arr;
  }

  next = () => {
    let arr = this.state.arr.slice();
    return arr[1];
  }

  last = () => {
    let arr = this.state.arr.slice();
    return arr[arr.length - 1];
  }
}

and access it in a main() method. In this case however, I would be using a parent Component, an example of which can be seen below:

class Main extends Component {

  constructor(props) {
    this.state = {queue: new Queue()};
  }

  render() {
    console.log(this.state.queue); 
    //displays the queue with its listed functions properly

    this.state.queue(new Date());
    //ERROR: 'cannot read property "slice" of undefined'
  }
}

So I can figure out the obvious occurrence of the Main class accessing the function queue() from the Queue class, but having this being bound to the Main class instead of the Queue class as intended.

So my question is this: using the ES6 arrow syntax, how do I maintain a binding of the this used in the Main class to the child instance of queue instead of to the Main class that calls the method?

In other words, how do I ensure the this.state.arr variable being accessed refers to the arr stored in the queue instance of Queue rather than the undeclared arr in the state of the Main class?

I apologize in advance if this is a duplicate question, but searching didn't get me any answers to this particular case so your help would be greatly appreciated.

EDIT: As Sidney pointed out below, I made a stupid mistake and omitted arr from my state in the Queue component. Sorry!

1 Answer 1

2

The error you're getting actually isn't related to this binding, and it would occur if you use the Queue class outside of React.

class Queue {
  constructor(props) {
    this.state = {message: "Test"}
  }

  queue(el) {
    let arr = this.state.arr.slice();
    arr.push(el);
    return arr;
  }

  dequeue = (el) => {
    let arr = this.state.arr.slice(1, this.state.arr.length);
    return arr;
  }

  next = () => {
    let arr = this.state.arr.slice();
    return arr[1];
  }

  last = () => {
    let arr = this.state.arr.slice();
    return arr[arr.length - 1];
  }
}

const ticketLine = new Queue()
ticketLine.queue('Bob')
ticketLine.queue('Sarah')

(Notice that extends Component and super() have been removed)

The error occurs on the first line of queue(), you're trying to access this.state.arr but you never defined it. So calling .slice() on undefined throws an error.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks so much for the reply Sidney, I noticed that just now and I'm definitely not surprised I made such a stupid mistake. I am however wondering about something else: since I never mount "Queue" in the "Main" class, when I input the following: console.log(this.state.queue); this.state.queue.queue(new Date()); console.log(this.state.queue); the arr variable in the queue state is never updated. Is there a workaround to this?
The arr variable in the Queue state doesn't change because you're using slice to copy the array in Queue.queue before adding the new element. This basically copies the array, adds an element to the copy, and discards the copy, since you never do anything else with the copy. You should store plain arrays or objects in React's state, not full class instances. You can create helper functions that take the current state and return a new state. You also might want to look into Redux for state management, and just have React do the rendering.

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.