【问题标题】:Why this way of non-mutating works in React.js?为什么这种非变异方式在 React.js 中有效?
【发布时间】:2021-08-30 20:51:58
【问题描述】:

我试图理解为什么这个例子是个好主意。 我正在学习 React,我发现这个函数将 complete 属性从 todo 更改。 我的问题是为什么这会起作用?因为我们有 const todo,它是现实中被改变的那个,而不是 newTodoList,它是我们返回的那个。我猜newTodoList 中的各个todo 也以某种方式发生了变化,但我不明白这是如何工作的,因为我们再次更改了新创建的const todo

function toggleTodo(id){
    const newTodoList = [...todos] 
    const todo = newTodoList.find(todo => todo.id === id)
    todo.complete = !todo.complete
    setTodos(newTodoList)
  }

【问题讨论】:

  • 这与 JavaScript 对象(和数组)的工作方式有关。这在技术上会改变状态,这很糟糕,但由于它会改变嵌套对象,因此不会影响 React 重新渲染的能力。这也是为什么它能够在只改变旧状态的同时修改新状态的原因。
  • @Brian Thompson 状态是 [...todos] 所以据我了解它不会改变它,它会克隆
  • 它是一个 shallow 克隆。嵌套对象/数组不是新实例,它们保留相同的对象引用。 this answer(在“说明”下)中有一些运行示例可能有助于说明我的意思。
  • 这很有帮助,谢谢!

标签: javascript arrays reactjs


【解决方案1】:

根据MDN Web Docs on constconst 声明创建了一个对值的只读引用。这并不意味着它持有的值是不可变的——只是变量标识符不能被重新分配。例如,在内容是对象的情况下,这意味着可以更改对象的内容(例如,它的属性)。

由于const todo 是一个对象,您可以更改其属性(即todo.complete

【讨论】:

  • 所以我知道const todo 持有对来自newTodoList 的值的引用,所以当我们更改complete 属性时,我们实际上通过这个在newTodoList 中更改它
  • 是的,你是对的。 const newTodoList = [...todos] 创建一个对象数组因此,const todo 持有对来自 newTodoList 的对象的引用。因此,当您更改todo 中的complete 属性时,它也会更改newTodoList 中的属性。
  • 感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多