React JS 中的状态正在被删除

Posted

技术标签:

【中文标题】React JS 中的状态正在被删除【英文标题】:State is being deleted in React JS 【发布时间】:2021-03-13 06:55:58 【问题描述】:

我是 React 新手。我正在尝试制作一个待办事项应用程序,但是每次更新状态时(我想更改一些布尔值),它都会被删除。请有人解释一下,我的代码中发生了什么,为什么它没有在函数todoDoneParent 中被删除。代码:

TodoApp 组件

class TodoApp extends Component 
  state = 
    todos: [
      id: 1, body: 'First Todo', isDone: false,
      id: 2, body: 'Second Todo', isDone: false,
      id: 3, body: 'Third Todo', isDone: false
    ]
  
  todoDoneParent= (id) => 
    let copyState = [...this.state.todos];
    let todo = copyState.filter(todo => todo.id == id );
    todo[0].isDone = true;
    let todos = copyState.filter(todo => todo.id != id );
    this.setState( todos: todo, todos ); 

    console.log('INSIDE todoDoneParent', this.state.todos);///////////////////////////////FIRST PRINT
  
  render() 
    console.log('INSIDE TodoApp.render()', this.state.todos); ///////////////////////////////SECOND PRINT
    return (
      <div className="allTodos">
      <Todos allTodos=this.state.todos todoDoneParent=this.todoDoneParent></Todos>
      </div>
    );
  

待办事项组件

class Todos extends Component 
  todoDone = (e) => 
    this.props.todoDoneParent(e.target.id);
  
  render()
    const todos= this.props.allTodos;
    const list = todos.length ? (
      todos.map(todo => 
        if(todo.isDone === false)
          return(<div className='todo' key=todo.id>
            <div className='todo-container'>
              <div>
                <p>todo.body</p>
              </div>
              <button className='btn' id=todo.id onClick=this.todoDone>
                Done
              </button>
            </div>
          </div>)
        
      )
    ) : (
      <div>
        <p>No todos</p>
      </div>
    );
    return(
      <div className='content'> 
        list
      </div>
    );
  

输出(在控制台中)

刚渲染时

INSIDE TodoApp.render() 
(3) […, …, …]
0: id: 1, body: "First Todo", isDone: false
1: id: 2, body: "Second Todo", isDone: false
2: id: 3, body: "Third Todo", isDone: false
length: 3
__proto__: Array(0)

当我点击任何按钮时

INSIDE todoDoneParent
(3) […, …, …]
0: id: 1, body: "First Todo", isDone: false
1: id: 2, body: "Second Todo", isDone: false
2: id: 3, body: "Third Todo", isDone: true
length: 3
__proto__: Array(0)

INSIDE TodoApp.render() 
(2) […, …]
0: id: 1, body: "First Todo", isDone: false
1: id: 2, body: "Second Todo", isDone: false
length: 2__proto__: Array(0)
那么为什么当我点击按钮 ```Done``` 时,它会在 ```todoDoneParent``` 函数中更新状态,但是,当它要被渲染时,我更新的那些状态会被删除?

【问题讨论】:

this.setState( todos: todo, todos ); 只是用todos 覆盖this.state.todos,这会过滤掉您想要标记为完成的那个。你希望这个函数做什么? @DrewReese 我希望这个函数将isDone 变量更新为true 【参考方案1】:

问题

this.setState( todos: todo, todos ); 只是用todos 覆盖this.state.todos,这会过滤掉您想要标记为完成的那个。它将它从todos 数组中删除。

另一个问题是类型比较问题,您的待办事项的id 类型是“数字”,但从onClick 事件返回的id 字段是类型“字符串”。 === 使用类型相等,即5 === '5' 为假,但5 == '5'

解决方案

如果我理解正确,您只是想将特定 todo 的 isDone 属性切换到 true,那么您应该将旧的 todos 映射到新的 todos 并在 @987654335 时更新特定的 todo @ 匹配。

待办事项

todoDoneParent = (id) => 
  this.setState((prevState) => (
    todos: prevState.todos.map((todo) =>
      todo.id === id
        ? 
            ...todo,
            isDone: true
          
        : todo
    )
  ));
;

待办事项

id 值转换回数字类型,以便在父组件中进行比较。

todoDone = (e) => 
  const  id  = e.target;
  this.props.todoDoneParent(Number(id));

【讨论】:

谢谢,但它没有更新任何东西,哪里有错误?我的意思是在我的代码中。 @mecdeality === 进行严格的类型比较,即5 === '5' 为假,但5 == '5' 为真,即'==' 尝试为比较进行类型强制。任务的id 是typeof "number",但e.target.id 是typeof "string",所以todo.id === id 条件始终是false 并且没有任何更新.. 你可以强制它返回一个数字:@ 987654346@ 然后=== 将起作用。【参考方案2】:

todoDoneParent 内部更改为此,这将起作用。您只需映射待办事项并更新待办事项并返回新列表。

todoDoneParent= (id) => 
  const updatedState = this.state.todos.map((item) => 
    if (item.id === id) 
      return 
        ...item,
        isDone: true
      
    
    return item;
  );
  this.setState( todos: updatedState );

【讨论】:

以上是关于React JS 中的状态正在被删除的主要内容,如果未能解决你的问题,请参考以下文章

如何从 React 状态数组中删除组件而不删除数组的其余部分?

React.js:无法访问状态对象中的对象属性

React.js - 功能组件中的状态未更新[重复]

React JS:setState中的previousState在状态更新后不保留先前状态的数据

React Js - Flux 中的状态管理

我在使用 React JS 中的状态时遇到分页问题