【问题标题】:how can i prevent todo app from creating blank task? [closed]如何防止待办事项应用程序创建空白任务? [关闭]
【发布时间】:2020-06-23 17:37:29
【问题描述】:

我是 react 初学者,我有 3 个问题 1)如何防止创建空白任务(见附图)

2)如何为 UI 的已检查任务添加删除线?

3)为什么会出现这个错误

警告:列表中的每个孩子都应该有一个唯一的“key”属性。

我的反应代码:

import React from "react";
import "./styles.css";
let id = 0
const Todo = props => (
  <li>
    <input type="checkbox" checked={props.todo.checked} onChange={props.onToggle} />
    <button onClick={props.onDelete}>delete</button>
    <span>{props.todo.text}</span>
  </li>
)
class App extends React.Component {
  constructor() {
    super()
    this.state = {
      todos: [],
    }
  }
  addTodo() {
    const text = prompt("TODO text please!")
    this.setState({
      todos: [
        ...this.state.todos,
        {id: id++, text: text, checked: false},
      ], 
    })
  }
  removeTodo(id) {
    this.setState({
      todos: this.state.todos.filter(todo => todo.id !== id)
    })
  }
  toggleTodo(id) {
    this.setState({
      todos: this.state.todos.map(todo => {
        
        if (todo.id !== id) return todo
        return {
          id: todo.id,
          text: todo.text,
          checked: !todo.checked,
        }
      })
    })
  }
  render() {
    return (
      <div>
        <div>Todo count: {this.state.todos.length}</div>
        <div>Unchecked todo count: {this.state.todos.filter(todo => !todo.checked).length}</div>
        <button onClick={() => this.addTodo()}>Add TODO</button>
        <ul>
          {this.state.todos.map(todo => (
            <Todo
              onToggle={() => this.toggleTodo(todo.id)}
              onDelete={() => this.removeTodo(todo.id)}
              todo={todo}
             
            />
          ))}
        </ul>
      </div>
    )
  }
}
export default App;

结果: todo-list result image

【问题讨论】:

  • 欢迎来到 SO!我肯定会鼓励使用谷歌搜索错误(甚至在 SO 上搜索),因为 Warning: Each child in a list should have a unique "key" prop. 是人们在渲染集合时在 React 中遇到的一个非常常见的错误。这个答案stackoverflow.com/questions/28329382/… 详细介绍了key 道具。

标签: javascript html reactjs react-dom


【解决方案1】:

查看 cmets 的更正:

import React from 'react';

let id = 0;
const Todo = (props) => (
   // style based on props
  <li style={{ textDecoration: props.todo.checked ? 'line-through' : ''}}>
    <input
      type='checkbox'
      checked={props.todo.checked}
      onChange={props.onToggle}
    />
    <button onClick={props.onDelete}>delete</button>
    <span>{props.todo.text}</span>
  </li>
);

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      todos: [],
    };
  }
  addTodo() {
    const text = prompt('TODO text please!');
    // only do this if text has value
    text && this.setState({
        todos: [...this.state.todos, { id: id++, text: text, checked: false }],
      });
  }
  removeTodo(id) {
    this.setState({
      todos: this.state.todos.filter((todo) => todo.id !== id),
    });
  }
  toggleTodo(id) {
    this.setState({
      todos: this.state.todos.map((todo) => {
        if (todo.id !== id) return todo;
        return {
          id: todo.id,
          text: todo.text,
          checked: !todo.checked,
        };
      }),
    });
  }
  render() {
    return (
      <div>
        <div>Todo count: {this.state.todos.length}</div>
        <div>
          Unchecked todo count:{' '}
          {this.state.todos.filter((todo) => !todo.checked).length}
        </div>
        <button onClick={() => this.addTodo()}>Add TODO</button>
        <ul>
          {this.state.todos.map((todo) => (
            <Todo
              key={todo.id} // need a unique key using id
              onToggle={() => this.toggleTodo(todo.id)}
              onDelete={() => this.removeTodo(todo.id)}
              todo={todo}
            />
          ))}
        </ul>
      </div>
    );
  }
}
export default App;

【讨论】:

    【解决方案2】:
    1. 如何防止创建空白任务(见附图)

    您必须在创建任务之前检查文本不是空字符串

      addTodo() {
        const text = prompt("TODO text please!")
        if(text !=== ""){ // <- check here
          this.setState({
            todos: [
              ...this.state.todos,
              {id: id++, text: text, checked: false},
            ], 
          })
        }
      }
    
    1. 如何为 UI 的已检查任务添加删除线?

    这可以通过使用text-decoration: line-through; 的 css 轻松完成,因此,使用该属性创建一个类(或者您也可以内联),如果任务状态已完成,则将该类添加到组件中

    .text-strike {
      text-decoration: line-through;
    }
    
    
    <Todo className={checked ? 'text-strike' : null}}
    
    1. 为什么会出现此错误

    每次你遍历一个数组来创建视图时,React 都需要一些东西来区分所有组件,所以当需要在 UI 中更新其中一个(重新渲染)时,它会确切地知道它是哪一个应该更新从而提高性能

      {this.state.todos.map(todo => (
         <Todo
            onToggle={() => this.toggleTodo(todo.id)}
            onDelete={() => this.removeTodo(todo.id)}
            todo={todo}
            key={somethingUnique}  // <- you need to add this key
         />
      ))}
    

    【讨论】:

      【解决方案3】:
      1. addTodo 函数中为空待办事项添加验证,如下所示
      addTodo() {
          const text = prompt("TODO text please!")
          if(text === undefined || text === "" || text?.trim() === ""){
          alert("You are lazy!!! enter proper value.");
          }else{
          this.setState({
            todos: [
              ...this.state.todos,
              {id: id++, text: text, checked: false},
            ], 
          })
          }
      
        }
      
      1. &lt;s&gt;标签醒目换行
      2. 您的 reacts 渲染机制需要区分元素,它使用key 作为区分器,以便轻松更新您的 for 循环中对该元素所做的任何更改,因为 dom 不代表 for 循环,它是 react 为您做的,那就是一种用于响应的接口,以了解它必须维护它。 因此,在您的待办事项列表中添加一个键,如下所示
       <Todo
                    onToggle={() => this.toggleTodo(todo.id)}
                    onDelete={() => this.removeTodo(todo.id)}
                    todo={todo}
                   key = {todo.id}
                  />
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-19
        • 1970-01-01
        • 2020-09-02
        相关资源
        最近更新 更多