Javascript 在反应、意外行为中推动数组

Javascript 在反应、意外行为中推动数组,javascript,arrays,reactjs,Javascript,Arrays,Reactjs,正在尝试创建待办事项列表应用程序 我希望我的todo项目具有唯一的键/id。我希望通过获取最后一个todo项目并将1添加到其id来创建todo项目id。如果该项目不存在,它将创建一个id为1的新项目 App.js: import React, {Component} from 'react'; import Todos from './Todos' import AddTodo from './AddForm' class App extends Component { state =

正在尝试创建待办事项列表应用程序

我希望我的todo项目具有唯一的键/id。我希望通过获取最后一个todo项目并将1添加到其id来创建todo项目id。如果该项目不存在,它将创建一个id为1的新项目

App.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>
    );
  }
}
相同的content 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}
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相同

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

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

AddForm.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;
import React,{Component}来自'React';
类AddTodo扩展组件{
状态={
内容:“”
}
handleChange=(e)=>{
这是我的国家({
内容:e.target.value
});
}
handleSubmit=(e)=>{
e、 预防默认值();
this.props.addTodo(this.state);
}
render(){
返回(
添加新待办事项
);
}
}
导出默认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;
从“React”导入React
常量Todos=({Todos,deleteTodo})=>{
const todoList=todos.length(
todos.map(todo=>{
返回(
{deleteTodo(todo.id)}>{todo.content}
)
})
) : (

您没有待办事项了

) 返回( {托多利斯特} ) } 导出默认TODO;
我猜您的问题来自于声明
以避免对类方法使用箭头符号的方式。相反,您应该将它们声明为常规函数,并在构造函数体中为您声明的每个方法执行一些操作,如
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指出了我在删除todo列表项时的id名称问题。我修好了。多谢各位


重复的id名称不知何故与我推动数组的方式有关。。。我仍然不能完全理解它,但它现在可以工作了。

问题似乎在于调用
addTodo
时传递的todo。由于todo数组或单个todo正在传递给
AddTodo
组件,我想知道在调用
AddTodo(?)
时,您传递给它的是什么。你能分享这部分代码吗?Thanks@AmerllicA我知道它没有遵循通常的模式,但是如果你确定你正在变异的对象是新的并且没有处于状态,它会造成什么伤害?有时,带有突变的代码的逻辑比没有突变的代码更清晰(尽管这不是一个很好的例子,因为这里使用rest语法很容易)@Alvaro I添加了代码的其余部分。我仍然不明白为什么ID:S是重复的,如果内容是相同的…@ Asistixasa:请考虑我的更新答案的建议。希望现在我能彻底解决你所有的困惑。希望,它终于让我接受了;)虽然这看起来是一个改进,但我不确定它是否回答了为什么ID会重复的问题-但问题中似乎没有足够的信息来回答真正的问题谢谢。我意识到我在删除项目时使用数组逻辑所犯的错误。不过我还是很困惑。我使用箭头函数的原因是为了访问类“this.state.”。如果我在我的类中使用你的函数,它会给我一个错误:“this.state.todos not defined”。。。有什么建议吗?