Reactjs 在不调用setState的情况下响应状态更新?

Reactjs 在不调用setState的情况下响应状态更新?,reactjs,Reactjs,我正在用React制作一个待办事项列表应用程序。“我的状态”中有项目,也有已删除的项目,因此可以恢复这些项目: state = { items: ['item 1', 'item 2', 'item 3'], deletedItems: ['item 4', 'item 5'] }; 因此,我的删除项函数必须从items状态删除该项,并将其置于deletedItems状态 removeItem(number) { const itemsState = this

我正在用React制作一个待办事项列表应用程序。“我的状态”中有项目,也有已删除的项目,因此可以恢复这些项目:

  state = {
    items: ['item 1', 'item 2', 'item 3'],
    deletedItems: ['item 4', 'item 5']
  };
因此,我的删除项函数必须从items状态删除该项,并将其置于deletedItems状态

 removeItem(number) {
    const itemsState = this.state.items;
    const deletedItemsState = this.state.deletedItems;

    const itemToBeDeleted = itemsState[number];
    deletedItemsState.push(itemToBeDeleted);

    itemsState.splice(number, 1);
    this.setState({ items: itemsState });
  }
上面的代码可以工作,但我不明白为什么deletedItems状态在没有调用setState的情况下被更新。我不是在遵循最佳实践吗

我不是在遵循最佳实践吗

没有。问题在于,您没有像您可能相信的那样使用临时变量,而是直接变异
deletedItems
。基本上:

const itemsState = this.state.items;
const deletedItemsState = this.state.deletedItems;
这些行不创建各自状态变量的副本,而是只创建对它们的引用

所以当你这么做的时候

deletedItemsState.push(itemToBeDeleted);
你正在直接改变状态!这是一个不,不,正如你可能已经知道的

为什么会发生这种情况? 要理解这一点,您必须了解基本值和复合值之间的赋值工作方式不同

例如:

var x = y;
如果
y
是字符串、数字、布尔值、null或未定义,则
x
将复制
y
的值。但是,如果是对象,数组或函数
x
将存储其引用


解决方案: 您需要做的是创建它们的浅拷贝。像这样:

const itemsState = this.state.items.slice();
const deletedItemsState = this.state.deletedItems.slice();
这将使
itemsState
deletedetemstate
分别从
This.state.item
This.state.deletedetems
中分离变量


演示: MyApp类扩展了React.Component{ 构造函数(){ 超级(); 此.state={ 项目:[“项目1”、“项目2”、“项目3”], deletedItems:[‘第4项’、‘第5项’] }; } removeItem=(数字)=>{ const itemsState=this.state.items; const deleteditemstate=this.state.deletedItems; const itemtobedelete=itemsState[number]; DeletedItemState.push(itemToBeDeleted); 项目状态拼接(编号1); 这是我的国家({ 项目:项目状态 }, () => { console.log(this.state); }); } render(){ 返回( 项目:
    {this.state.items.map((item,i)=>
  • {item}Remove
  • )}
删除的项目:
    {this.state.deletedItems.map(item=>
  • {item}
  • )}
); } } render(,document.getElementById(“app”)

我不是在遵循最佳实践吗

没有。问题在于,您没有像您可能相信的那样使用临时变量,而是直接变异
deletedItems
。基本上:

const itemsState = this.state.items;
const deletedItemsState = this.state.deletedItems;
这些行不创建各自状态变量的副本,而是只创建对它们的引用

所以当你这么做的时候

deletedItemsState.push(itemToBeDeleted);
你正在直接改变状态!这是一个不,不,正如你可能已经知道的

为什么会发生这种情况? 要理解这一点,您必须了解基本值和复合值之间的赋值工作方式不同

例如:

var x = y;
如果
y
是字符串、数字、布尔值、null或未定义,则
x
将复制
y
的值。但是,如果是对象,数组或函数
x
将存储其引用


解决方案: 您需要做的是创建它们的浅拷贝。像这样:

const itemsState = this.state.items.slice();
const deletedItemsState = this.state.deletedItems.slice();
这将使
itemsState
deletedetemstate
分别从
This.state.item
This.state.deletedetems
中分离变量


演示: MyApp类扩展了React.Component{ 构造函数(){ 超级(); 此.state={ 项目:[“项目1”、“项目2”、“项目3”], deletedItems:[‘第4项’、‘第5项’] }; } removeItem=(数字)=>{ const itemsState=this.state.items; const deleteditemstate=this.state.deletedItems; const itemtobedelete=itemsState[number]; DeletedItemState.push(itemToBeDeleted); 项目状态拼接(编号1); 这是我的国家({ 项目:项目状态 }, () => { console.log(this.state); }); } render(){ 返回( 项目:
    {this.state.items.map((item,i)=>
  • {item}Remove
  • )}
删除的项目:
    {this.state.deletedItems.map(item=>
  • {item}
  • )}
); } } render(,document.getElementById(“app”)
这不是处理应用程序中状态更改的正确方法

比如说这条线,

const itemsState = this.state.items;
它创建一个变量itemsState,该变量指向this.state.items。因此,对itemsState所做的任何更改都将在state.items中更改。这会改变你的数据

最佳实践是使用库(如)进行状态更新,或者将状态对象克隆到变量中,然后对其执行突变。完成后,最后使用setState()更新状态

下面是一段代码片段,解释如何使用Object.assign()进行克隆。正如您在代码段中看到的那样,这不会更改原始状态变量

var状态={
项目:[“项目1”、“项目2”、“项目3”],
deletedItems:[‘第4项’、‘第5项’]
};
函数removeItem(编号){
const itemsState=Object.assign([],this.state.items);
const deleteditemstate=Object.assign([],this.state.deletedItems);
const itemtobedelete=itemsState[number];
DeletedItemState.push(itemToBeDeleted);
项目状态拼接(编号1);
//this.setState({items:itemsState});
console.log(状态);
}

移除项目(1)这不是处理应用程序中状态更改的正确方法

比如说这条线,

const itemsState = this.state.items;
它创建一个变量itemsState,该变量指向this.state.items。因此,对itemsState所做的任何更改都将在state.items中更改。这会改变你的数据。