React Todo Checkbox一次为所有列出的项目设置样式

时间:2018-02-27 23:59:36

标签: javascript arrays reactjs

我正在尝试使用React创建一个待办事项列表。我可以在显示区域显示列表,也可以删除项目。但是,当我单击一个复选框时,将选中所有复选框,并将该类应用于所有列表项。我不确定我做错了什么。

我尝试使用与删除项目(使用过滤器)相同的逻辑,但它不起作用。我在这里查看其他案例,但他们主要是关于如何使用jQuery。

Here是我问题的工作示例。

这是List类

class List extends Component {

  state={
    check: false,
    strike: 'none'
  }

  onCheck(item){
    this.setState({check: !this.state.check})
    if (this.state.strike === 'none'){
      this.setState({strike: 'line-through'})
    } else {
      this.setState({strike: 'none'})
    }
  }

  render() {
    const strike = {
      textDecoration: this.state.strike,
    }

  return (
    <ul className='list-style'>
      { this.props.items.map((item, index) =>
         <li key={index}>
           <div className="outer-div">
             <div className="item-checkbox">
               <input type="checkbox" checked={this.state.check}
                 onChange={() => this.onCheck(item)} />
              </div>
              <div className="item-text">
                 <span style= {strike}> {item} </span>
              </div>
              <div className="item-remove-div">
                <button className="item-remove" onClick={() => this.props.onDeleteList(index)}>
                  Remove
                </button>
              </div>
            </div>
             <br />
         </li>
       )}
    </ul>
  )}
}

export default List;

这是主类:

class Main extends Component {

  state = {
    items: [],
    term : "",
  }

 onChange(event){
   this.setState({ term: event });
 }

 onDelete= (item) =>{
   // this.setState ({
   //   items: this.state.items.filter((i) => i.index !== item.index)
   // })
   this.state.items.splice(item, 1);
   this.setState({items: this.state.items});
 }

  onSubmit= (event) => {
    event.preventDefault();
    if (this.state.term.length > 0){
      this.setState({
        term: '',
        items: [...this.state.items, this.state.term]
      });
    }
  }

  render() {
    return (
      <div className="center">
       <h1 className="header" > TODO-LIST </h1>
       <div className='mainCenter'>
        <form className="App" onSubmit={this.onSubmit}>
          <input placeholder="add task" value={this.state.term} onChange={(e) => this.onChange(e.target.value)}
          className="inputField"/>
          <button>Add to the List</button>
        </form>
        <List items={this.state.items}  onDeleteList={this.onDelete}/>
        <div className="footer-outer">
          <span className="footer"> Number of completed items in an array:  {this.state.items.length} </span>
        </div>
      </div>
    </div>
    );
  }
}

2 个答案:

答案 0 :(得分:2)

我修改了你的SlackBlitz。现在,您可以正确添加新待办事项,检查个人任务(在todo点击时切换检查)并在页脚中查看正确的checked计数器。 查看todo-list-react演示。

import React, { Component } from 'react';
import TodoList from './List';
import './style.css';

class Main extends Component {
  constructor() {
    super();
    this.state = {
      items: [],
      term: ''
    };
  }

  handleChange = event => {
    this.setState({ term: event.target.value });
  }

  handleItemClick = ({ value, checked }) => {
    this.setState({
      items: this.state.items.map(item => item.value === value ? { value, checked: !checked } : item)
    });
  }

  onSubmit = event => {
    event.preventDefault();

    if (this.state.term.length > 0) {
      this.setState({
        term: '',
        items: [...this.state.items, { value: this.state.term, checked: false }]
      });
    }
  }

  handleDelete = index => {
    console.info('todo: remove todo at index', index);
    // deletion logic... keep in mind that using index as key properties on jsx could breaks the correct functioning of this component.
  }

  render() {
    return (
      <div className="center">
       <h1 className="header" > TODO-LIST </h1>
       <div className='mainCenter'>
       <form className="App" onSubmit={this.onSubmit}>
          <input placeholder="add task" value={this.state.term} onChange={this.handleChange}
          className="inputField"/>
          <button>Add to the List</button>
        </form>
        <TodoList 
          onTodoClick={this.handleItemClick}
          onDelete={this.handleDelete}
          todos={this.state.items}
        />
        <div className="footer-outer">
          <span className="footer">
            Number of completed items in an array:
            {this.state.items.filter(item => item.checked).length}
          </span>
        </div>
      </div>
    </div>
    );
  }
}

export default Main
import React, { Component } from 'react';
import './style.css';

class List extends Component {
  render() {
    const { todos, onTodoClick, onDelete } = this.props;
    return (
      <ul className='list-style'>
        {
          todos.map((item, index) =>
          <li key={index}>
            <div className="outer-div">
              <div className="item-checkbox">
                <input type="checkbox" checked={item.checked}
                  onChange={() => onTodoClick(item)} />
                </div>
                <div className="item-text">
                  <span style={checkboxStyle(item.checked)}>{item.value}</span>
                </div>
                <div className="item-remove-div">
                  <button className="item-remove" 
                    onClick={() => onDelete(index)}>
                    Remove
                  </button>
                </div>
              </div>
              <br />
          </li>
        )}
      </ul>
    )}
  }

function checkboxStyle(checked) {
  return {
      textDecoration: checked? 'line-through' : 'none',
    };
}

export default List;

enter image description here

除了这个答案,我建议你考虑从数组索引的每个jsx-element differen中添加一个唯一的key属性。当前的实现没有问题,但是一旦你开始删除todo项目可能会显示错误的数据。

阅读React文档中的List and KeysMedium上的这篇文章,其中介绍了使用indix作为键时可能出现的错误。

答案 1 :(得分:1)

您的所有列表项目被删除的原因&#39;是因为您只为列表中的所有项目保留了一个州。您需要为列表中的每个项目设置checkedstrike状态。但是,当我查看您的评论时,我意识到您已经知道了。

您在代码中还有其他几个不一致的地方:

 onDelete= (item) =>{
   this.state.items.splice(item, 1);
   this.setState({items: this.state.items});
 }

state进行直接更改可能会导致意外错误和异常行为。更好的方法是:

onDelete = (item) => {
  const items = this.state.items.slice();
  items.splice(item, 1);
  this.setState({
    items: items,
  });
}

有关详细信息,请参阅此文章: https://medium.com/pro-react/a-brief-talk-about-immutability-and-react-s-helpers-70919ab8ae7c