繁体   English   中英

在 React 中推送到数组,意外行为

[英]Pushing to array in React, unexpected behaviour

尝试制作一个待办事项列表应用程序

我希望我的待办事项有一个唯一的键/ID。 我想通过获取最后一个待办事项并在其 ID 上加 1 来创建待办事项 ID。 如果该项目不存在,它会创建一个 id = 1 的新项目。

应用程序.js:

import React, {Component} from 'react';
import Todos from './Todos'
import AddTodo from './AddForm'

class App extends Component {

  state = {
    todos: [
      {id: 1, content: 'buy milk'},
      {id: 2, content: 'play nintendo'}
    ]
  }

 addTodo = (todo) => {
    if (this.state.todos[0])
    {
      todo.id = this.state.todos[this.state.todos.length-1].id +1;
      let todos = [...this.state.todos];
      todos.push(todo);
      this.setState({
        todos: todos
      });
    }
    else
    {
      this.setState({
        todos: [
          {id: 1, content: todo.content}
        ]
      });
    }
    console.log(this.state.todos);
  }


  render() {
    return(
      <div className="todo-app container">
        <h1 className="center blue-text">Todos:</h1>
        <Todos deleteTodo={this.deleteTodo} todos={this.state.todos}/>
        <AddTodo addTodo={this.addTodo} />
      </div>
    );
  }
}

这几乎有效。 如果项目具有独特的内容,我可以添加新项目,但是当项目具有相同的内容时会出现问题。

独特的内容 console.log:

0: {content: "buy milk", id: 1}
1: {content: "play nintendo", id: 2}
2: {content: "adrfhahhafafdhafhafhhfa", id: 3}
3: {content: "adrfhahhafafdhafhafhhfaafhafhfah", id: 4}
4: {content: "adrfhahhafafdhafhafhhfaafhafhfahafhfahafh", id: 5}
5: {content: "adrfhahhafafdhafhafhhfaafhafhfahafhfahafhafhafhfah", id: 6}

相同的内容 console.log:

0: {content: "buy milk", id: 1}
1: {content: "play nintendo", id: 2}
2: {content: "adrfhahhafafdhafhafhhfa", id: 3}
3: {content: "adrfhahhafafdhafhafhhfaafhafhfah", id: 4}
4: {content: "adrfhahhafafdhafhafhhfaafhafhfahafhfahafh", id: 5}
5: {content: "adrfhahhafafdhafhafhhfaafhafhfahafhfahafhafhafhfah", id: 7}
6: {content: "adrfhahhafafdhafhafhhfaafhafhfahafhfahafhafhafhfah", id: 7}

如您所见,如果内容相同,则 id 相同。

我知道这可能是在反应中添加 id:s 的错误方法,但我想了解发生了什么。 提前致谢。

编辑:如果项目被删除,Yevgen 指出了我的逻辑缺陷,但我仍然不明白为什么ID:s 重复。 有人要求提供其余的代码,所以我全部添加了。

添加表单.js

import React, {Component} from 'react';

class AddTodo extends Component {
  state = {
    content: ''
  }

  handleChange = (e) => {
    this.setState({
      content: e.target.value
    });
  }

  handleSubmit = (e) => {
    e.preventDefault();
    this.props.addTodo(this.state);
  }

  render(){
    return (
    <div>
      <form onSubmit={this.handleSubmit}>
        <label>Add new todo</label>
        <input type="text" onChange={this.handleChange} />
      </form>
    </div>
    );
  }
}

export default AddTodo;

Todos.js

import React from 'react'

const Todos = ({todos, deleteTodo}) => {
  const todoList = todos.length ? (
    todos.map(todo => {
      return (
        <div className="collection-item" key={todo.id}>
          <span onClick={() => {deleteTodo(todo.id)}}>{todo.content}</span>
        </div>
      )
    })
  ) : (
    <p className="center">You have no todos left</p>
  )
  return (
    <div className="todos collection">
      {todoList}
    </div>
  )
}

export default Todos;

我的猜测是您的问题来自您声明<AddForm />组件状态的方式。 您应该在 constrictor 体内完成此操作,如this.state 您当前所做的是全局变量声明。 因此,它不会绑定到您的应用程序状态,并且您的id未正确分配。

除此之外,您的addTodo()看起来过于复杂且容易出错(您不能依赖数组长度来获得最大使用id ,因为删除除 last 之外的项目会破坏逻辑)。

此外,通常建议避免对类方法使用箭头符号。 相反,您应该将它们声明为常规函数并在构造函数主体中为您声明的每个方法做一些事情,例如this.addTodo = this.addTodo.bind(this) 否则,如果你非常喜欢箭头函数,你可能会更喜欢函数组件。

按照您分配自动递增id的逻辑(因此,已删除项目的id永远不会被重用)并将具有属性content对象传递给addTodo() ,您可以简单地完成:

addTodo({content}){
   const id = Math.max(...this.state.todos.map(({id}) => id),0)+1
   this.setState({todos:[...this.state.todos, {id, content}]})
}

我能够通过解决这个问题来让它工作:

 if (this.state.todos[0])
    {
      todo.id = this.state.todos[this.state.todos.length-1].id +1;
      let todos = [...this.state.todos];
      todos.push(todo);
      this.setState({
        todos: todos
      });
    }

有了这个:

 if (Array.isArray(this.state.todos) && this.state.todos.length)
    {
      todo.id = Math.max(...this.state.todos.map(({id}) => id),0)+1
      let todos = [...this.state.todos];
      todos.push({id: todo.id, content: todo.content})
      this.setState({
        todos: todos
      })
    }

Yevgen 在删除待办事项列表项时指出了我的 id 名称问题。 我修好了它。 谢谢你。

重复的 id 名称以某种方式与我推送到数组的方式有关......我仍然不完全理解它,但它现在可以工作......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM