ReactJs Todo List推送状态

时间:2017-06-21 08:14:29

标签: javascript ecmascript-6

我已经在reactjs中编写了todo列表的开头,并且正在寻求改进todos如何添加到状态的功能。目前,我将put中的值连接到处于状态的数组中,然后拼接掉所选的li元素。添加第一个待办事项时似乎有点儿麻烦。我应该使用反应不变性助手来实现这一目标吗?似乎过度杀戮增加了另一件可以在普通js中实现的东西。

//Input component
const Input = props => {
  return (
    <div className="form-group">
      <input
        className="form-control"
        value={props.value}
        onChange={props.update}
        type="text"
      />
      <button className="btn btn-default" onClick={props.handleClick}>
        Add Todo
      </button>
    </div>
  );
};
//display list of todos
const Displaytodo = (props) => {
  const todolist = props.todo;
  const listItems = todolist.map((todo, index) =>
    <li
      className={
       props.highlight ? 'list-unstyled todoItem highlight' : 'list-unstyled todoItem '
      }
      key={index}>
      {todo}
      <div
        onClick={props.removeTodo.bind(this, index)}
        className="removeTodo">
        <i className="fa fa-trash" />
      </div>
      <div onClick={props.changeHighlight.bind(this,index)} className="checkTodo">
        <i className="fa fa-check-circle" onClick={props.highlight} />
      </div>
    </li>
  );

  return <ul className="todos">{listItems}</ul>;
};
//controlled state component
class Layout extends React.Component {
  constructor() {
    super();
    this.state = { text: "Hello", todo: [], highlight: false };
  }
  update(e) {
    this.setState({ text: e.target.value });
  }
  handleClick() {
    const text = this.state.text;
    if (text.length > 0) {
      this.setState(
        { todo: this.state.todo.concat(text), text: "", highlight: false },
        function() {
          console.log(this.state.todo);
        }
      );
    } else {
      alert("please enter something");
    }
  }
  removeTodo(e) {
    this.state.todo.splice(e, 1);
    this.setState({ todo: this.state.todo });
  }

  changeHighlight(index, e) {
    const highlight = this.state.highlight;

    this.setState(prevState => ({
      highlight: !prevState.highlight
    }));
  }

  render() {
    return (
      <div className="container">
        <div className="row">

          <div className="col-md-4 col-md-offset-4">
            <div className="wrapper">
              <h1>Todo List</h1>

              <Input
                value={this.state.text}
                update={this.update.bind(this)}
                handleClick={this.handleClick.bind(this)}
              />
              <Displaytodo
                removeTodo={this.removeTodo.bind(this)}
                todo={this.state.todo}
                changeHighlight={this.changeHighlight.bind(this)}
                highlight={this.state.highlight}
              />
            </div>

          </div>
        </div>
      </div>
    );
  }
}

const app = document.getElementById("app");

ReactDOM.render(<Layout />, app);

https://codepen.io/mhal12/pen/MomWVg

此外,当用户点击绿色勾选时,它会通过切换类突出显示该行&#39;突出显示&#39;关闭和打开,但在控制台中它给出了一个错误。链接到

https://facebook.github.io/react/docs/error-decoder.html?invariant=94&args[]=onClick&args[]=boolean

1 个答案:

答案 0 :(得分:1)

只需删除onClick上的<i className="fa fa-check-circle" onClick={props.highlight} />

至于每个todo的突出显示,它有点复杂。您必须在每个id上设置todo,然后将id传递给changeHighlight功能。您必须从全局状态中删除突出显示,并在每个highlight上分配todo布尔值。然后你必须相应地显示todos

removeTodo函数的相同内容,您传入id以在父组件中删除它。

这里是完整的代码:

const Input = props => {
  return (
    <div className="form-group">
      <input
        className="form-control"
        value={props.value}
        onChange={props.update}
        type="text"
      />
      <button className="btn btn-default" onClick={props.handleClick}>
        Add Todo
      </button>
    </div>
  );
};
const Displaytodo = (props) => {
  const changeHighlight = function(id) {
    props.changeHighlight(id);
  }

  const removeTodo = function(id) {
    props.removeTodo(id);
  }

  const todolist = props.todo;
  const listItems = todolist.map((todo, index) =>
    <li
      className={
       todo.highlight ? 'list-unstyled todoItem highlight' : 'list-unstyled todoItem '
      }
      key={todo.id}>
      {todo.text}
      <div
        onClick={removeTodo.bind(event, todo.id)}
        className="removeTodo">
        <i className="fa fa-trash" />
      </div>
      <div onClick={changeHighlight.bind(event, todo.id)} className="checkTodo">
        <i className="fa fa-check-circle" />
      </div>
    </li>
  );

  return <ul className="todos">{listItems}</ul>;
};
class Layout extends React.Component {
  constructor() {
    super();
    this.state = {text: "Hello", todo: []};
  }
  update(e) {
    this.setState({ text: e.target.value });
  }
  handleClick() {
    const text = this.state.text;
    if (text.length > 0) {
      this.setState(
        { todo: this.state.todo.concat({
          id: this.state.todo.length + 1,
          text: this.state.text,
          highlight: false
        }), text: ""},
        function() {
          console.log(this.state.todo);
        }
      );
    } else {
      alert("Please enter something");
    }
  }
  removeTodo(id) {
    let todos = this.state.todo;

    for (let i = 0; i < todos.length; i++) {
      let todo = todos[i];
      if (todo.id == id) {
        todos.splice(i, 1);
      }
    }

    this.setState({ todo: todos });
  }

  changeHighlight(id) {    
    let todos = this.state.todo;

    for (let i = 0; i < todos.length; i++) {
      let todo = todos[i];
      if (todo.id == id) {
        todos[i].highlight = !todos[i].highlight;
      }
    }

    this.setState({
      todo : todos
    });
  }

  render() {
    return (
      <div className="container">
        <div className="row">

          <div className="col-md-4 col-md-offset-4">
            <div className="wrapper">
              <h1>Todo List</h1>

              <Input
                value={this.state.text}
                update={this.update.bind(this)}
                handleClick={this.handleClick.bind(this)}
              />
              <Displaytodo
                removeTodo={this.removeTodo.bind(this)}
                todo={this.state.todo}
                changeHighlight={this.changeHighlight.bind(this)}
              />
            </div>

          </div>
        </div>
      </div>
    );
  }
}

const app = document.getElementById("app");

ReactDOM.render(<Layout />, app);