1

I want to create component with table which have add, update, delete operations. But when I try to add some test element to array I got this error

Uncaught TypeError: this.documents is not iterable at HTMLButtonElement.addNewDocument

This is simple code, but I can't figure where is bug.

@State()
documents: string[] = [];

addNewDocument() {
 this.documents= [... this.documents, "test2"];
}

render() {

   return (
      <Host>
          <button onClick={this.addNewDocument} type="button" class="btn btn-success">
            <i class="fa fa-plus"></i>
            <span class="btn-text">add new</span>
          </button>

          {this.documents && this.documents.length ? (

            <div>

              <table>
                <thead>
                  <tr>
                    <th>Name</th>
                  </tr>
                </thead>
                <tbody>
                  {this.documents.map(document => (
                    <tr>
                      <td>{document}</td>
                    </tr>
                  ))}
                </tbody>
              </table>

            </div>
          ) : (
            <div>Loading...</div>
          )}

        </div>
      </Host>
    );
  }
Paul Maclean
  • 19
  • 1
  • 3

1 Answers1

0

The problem is the context (i.e. the value of this).

Because of how you attach the event handler (onClick={this.addNewDocument}) the this keyword within addNewDocument will refer to the button element, not your component instance.

Basically it's equivalent to button.addEventListener(function() { this.documents = [ ...this.documents, "test2"] } which would throw the same error.

There are two ways of preventing this:

1. Arrow function

Arrow functions inherit the context from the parent:

<button onClick={() => this.addNewDocument()}></button>

2. Bind

You can manually set the context using .bind().

<button onClick={this.addNewDocument.bind(this)}></button>
Thomas
  • 8,426
  • 1
  • 25
  • 49