3
\$\begingroup\$

This is my first attempt at React and I don't want to pick up any bad habits for the long term. The code is adopted from a example app, but I have added a fair amount of new features. I.e.

Clicking on the item allows it to be edited Delete Option Option to mark the items as Complete / Uncompleted

Any feedback would be appreciated.

    var data = [
    {text: "Click me to edit!",
    key: 43534534534534534,
    show: false,
    completed: false},
  {text: "This is a long task that fits over multiple lines!",
    key: 2453534566554353,
    show: false,
    completed: false
  }, 
  {    text: "This is a complted task",
    key: 4353443534534534534,
    show: false,
    completed: true
  }
]

class App extends React.Component {
    inputElement = React.createRef() 
  constructor() {
    super();
    this.state = {
      items: data,
            currentItem: {
        text: '',
        key: '',
        show: false,
        completed: false
      },

    };
  }

  changeStatus = key =>{
    const tempItems = this.state.items.slice()

    tempItems.forEach((item) => {
      if (item.key===key){
        item.completed = !item.completed;
      }

    })
    this.setState({
      items: tempItems,
    })
  } 

    deleteItem = key => {
    const filteredItems = this.state.items.filter(item => {
      return item.key !== key
    })
    this.setState({
      items: filteredItems,
    })

  }

   showEditItemForm = (key) => {
    const tempItems = this.state.items.slice()

    tempItems.forEach((item) => {
      if (item.key===key && !item.completed){
        item.show = !item.show;
      }
      else
      {
        item.show = false
      }
    })
    this.setState({
      items: tempItems,
    })
  }

  editItem = (key, NewText) => {
    const tempItems = this.state.items.slice()
    tempItems.forEach((item) => {
      if (item.key===key){
        item.text = NewText
        item.show = false
        item.completed = false
      }

    })
    this.setState({
      items: tempItems,
    })
  }


    handleInput = e => {
    const itemText = e.target.value
    const currentItem = { text: itemText, key: Date.now() }
    this.setState({
      currentItem,
    })
  }
  addItem = e => {
    e.preventDefault()
    const newItem = this.state.currentItem
    if (newItem.text !== '') {
      const items = [...this.state.items, newItem]
      this.setState({
        items: items,
        currentItem: { text: '', key: '', show: false },
      })
       data = JSON.stringify(state.items)

    }}

  render() {
    return (
    <div  className="App">
              <TodoList
          addItem={this.addItem}
          inputElement={this.inputElement}
          handleInput={this.handleInput}
          currentItem={this.state.currentItem}
        />
   <TodoItems entries={this.state.items} deleteItem={this.deleteItem} editItem={this.editItem} showEditItemForm={this.showEditItemForm} changeStatus = {this.changeStatus} />
      </div>
    );
  }
}

class TodoList extends React.Component {
  componentDidUpdate() {
    this.props.inputElement.current.focus()
  }
  render() {
    return (
      <div className="todoListMain">
        <div className="header">
          <form onSubmit={this.props.addItem}>
            <input
              placeholder="Task"
              ref={this.props.inputElement}
              value={this.props.currentItem.text}
              onChange={this.props.handleInput}
            />
            <button type="submit"> Add Task </button>
          </form>
        </div>
      </div>
    )
  }
}



class TodoItems extends React.Component {

  constructor() {
    super()
    this.state = {
      updatedText: '',
    }
    this.updateText = this.updateText.bind(this);

  }


updateText(event){
  this.setState({updatedText : event.target.value})
  }

  createTasks = item => {

    var txtClass = item.completed ? 'completed' : 'uncompleted';

    return (
      <li key={item.key}>  

       {  !item.show && 
       <div className="item-container">
       <span className="control-containers checkbox-padding">
       <input className="status-checkbox" type="checkbox" name="status" value="" checked={item.completed} onChange={() => this.props.changeStatus(item.key)}></input>
        </span>
        <span className={`item-text ${txtClass}`} onClick={() => this.props.showEditItemForm(item.key)}>{item.text}</span>
        <span className="control-containers">
        <button className="delete-button" onClick={() => this.props.deleteItem(item.key)}>Delete</button>
        </span>

        </div>
       }
        {item.show &&
        <div> 

          <input className="edit-input" type="text" name="ItemText" title="Item Text" autoFocus={true} defaultValue={item.text}  onFocus={this.updateText} onChange={this.updateText}  />
          <button className="save" onClick={() => this.props.editItem(item.key, this.state.updatedText)} >Save</button>
          <button className="cancel" onClick={() => this.props.showEditItemForm(item.key)}>Close</button>

        </div>
        }





      </li>
    )
  }
  render() {
    const todoEntries = this.props.entries
    const listItems = todoEntries.map(this.createTasks)

    return <ul className="theList">{listItems}</ul>
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

Working demo can be found here: Codepen Demo

\$\endgroup\$
  • \$\begingroup\$ (Welcome to Code Review!) (The indentation of your code looks inconsistent, starting with var data = […].) \$\endgroup\$ – greybeard Dec 14 '18 at 21:34
  • \$\begingroup\$ I had a right game getting the app working on a pen. It was coded in vs code in multiple files. The data in the var was originally a js file. While converting the code in a format so it works on a pen, all code formatting went out of the window. \$\endgroup\$ – SANM2009 Dec 14 '18 at 21:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.