todoapp.tsx


import React, { Component, MouseEvent, ChangeEvent } from 'react';

type Item = {
  name: string;
  completed: boolean;
};

interface TodoState {
  items: Item[];    // existing items
  newName: string;  // text in the field to add a new name
}

export class ToDoApp extends Component<{}, TodoState> {

  constructor(props: {}) {
    super(props);
    this.state = { items: [], newName: "" };
  }

  // Called when the user checks the box next to an uncompleted item. The
  // second parameter is the index of that item in the list.
  completeItem = (_: ChangeEvent<HTMLInputElement>, index: number): void => {
    const items = this.state.items.slice(0);
    items[index] = {name: items[index].name, completed: true};
    this.setState({items: items});

    setTimeout(() => this.removeItem(index), 500); 
  }

  // Removes the item at the given index
  removeItem = (index: number): void => {
    const items = this.state.items.slice(0);
    items.splice(index, 1);
    this.setState({items: items});
  }

  // Called when the user clicks on the button to add the new item.
  addItem = (_: MouseEvent<HTMLButtonElement>): void => {
    const name = this.state.newName.trim().replace('\t', ' ');  // no tabs
    if (name.length > 0) {
      const items = this.state.items.slice(0);
      items.push({name: name, completed: false});
      this.setState({items: items, newName: ""});
    }
  }

  // Called each time the text in the new item name field is changed.
  setNewName = (evt: ChangeEvent<HTMLInputElement>): void => {
    this.setState({newName: evt.target.value});
  }

  render = (): JSX.Element => {
    const items: JSX.Element[] = [];
    for (let i = 0; i < this.state.items.length; i++) {
      if (this.state.items[i].completed) {
        items.push(
          <div className="form-check" key={i}>
            <input className="form-check-input" type="checkbox"
                id={"check" + i} checked={true} readOnly={true} />
            <label className="form-check-label completed" htmlFor={"check" + i}>
              {this.state.items[i].name}
            </label>
          </div>);
      } else {
        items.push(
          <div className="form-check" key={i}>
            <input className="form-check-input" type="checkbox"
                id={"check" + i} checked={false}
                onChange={evt => this.completeItem(evt, i)} />
            <label className="form-check-label" htmlFor={"check" + i}>
              {this.state.items[i].name}
            </label>
          </div>);
      }
    }

    return (
      <div>
        <h2>To-Do List</h2>
        {items}
        <p className="instructions">Check the item to mark it completed.</p>
        <p className="more-instructions">New item:
          <input type="text" className="new-item"
              value={this.state.newName}
              onChange={this.setNewName} />
          <button type="button" className="btn btn-link"
              onClick={this.addItem}>Add</button>
        </p>
      </div>);
  }
}

Full Code