推入状态数组的正确方法


122

我似乎在将数据推入状态数组时遇到问题。我正在尝试以这种方式实现它:

this.setState({ myArray: this.state.myArray.push('new value') })

但是我相信这是不正确的方式,并导致可变性问题?

Answers:


145

数组推送返回长度

this.state.myArray.push('new value')返回扩展数组的长度,而不是数组本身。Array.prototype.push()

我猜您希望返回的值是数组。

不变性

似乎这是React的行为:

切勿直接更改this.state,因为之后调用setState()可能会替换您所做的更改。将此this.state视为不可变的。React.Component

我猜,您会这样做(不熟悉React):

var joined = this.state.myArray.concat('new value');
this.setState({ myArray: joined })

1
当我这样做console.log(this.state.myArray)的时候,总是落后一步。知道为什么吗?
SI 8

@ Si8好吧,不幸的是我并没有使用React太多。但是文档说: setState()将更改状态加入组件状态,并告诉React该组件及其子级需要使用更新后的状态重新呈现。 因此,我想它只是在设置之后没有更新。您能否发布一个代码示例,在哪里可以看到您正在设置和记录的代码点?
顿·塔马斯

感谢您的回复。它是异步的,因此不会立即显示更改。但是setState确实有一个回调,该回调确实显示了正确的值。再次感谢。
SI 8

w3schools.com/jsref/jsref_concat_array.asp concat连接两个数组(不是数组和字符串), .concat('new value'); 应该是 .concat(['new value']);
Manohar Reddy Poreddy

1
@ManoharReddyPoreddy非数组值对该concat()方法完全有效。请参阅:developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/…要连接到新数组中的数组和/或值。
MártonTamás19年

176

使用es6可以像这样完成:

this.setState({ myArray: [...this.state.myArray, 'new value'] }) //simple value
this.setState({ myArray: [...this.state.myArray, ...[1,2,3] ] }) //another array

传播语法


1
我做了同样的事情,有两种情况myArray可以有值,而没有。因此,如果它已经具有值,则可以正常工作。但是在没有数据的情况下,它不会用“新值”更新状态。有锡吗?
克里娜·索尼

它应该与任何数组一起使用,不管它是否有值,无论如何都将被解构。也许其他地方有问题。您能显示一个示例代码吗?
Aliaksandr Sushkevich

嗨,请参阅我的评论@Tamas答案。这只是控制台中的示例。我尝试了myArray:[... this.state.myArray,'new value']更新我的状态数组。但是它只包含最后一个值。您能告诉我解决方案吗?
约翰西

@Johncy我不确定您的问题是否与此问题有关,请尝试提出一个单独的问题并描述预期的行为,我将尽力帮助您。
Aliaksandr Sushkevich,

5
每对文档做出反应:“因为this.propsthis.state可异步更新,你不应该依赖于它们的值来计算下一个状态。” 在修改数组的情况下,由于数组已经作为属性存在,this.state并且您需要引用其值以设置新值,因此您应该使用setState()接受具有前一状态的函数作为参数的形式。例如:this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] }));请参见:reactjs.org/docs/...
邦哥

103

绝不建议直接更改状态。

在更高版本的React中,建议的方法是在修改状态以防止竞争情况时使用updater函数:

将字符串推到数组的末尾

this.setState(prevState => ({
  myArray: [...prevState.myArray, "new value"]
}))

将字符串推送到数组的开头

this.setState(prevState => ({
  myArray: ["new value", ...prevState.myArray]
}))

将对象推到数组的末尾

this.setState(prevState => ({
  myArray: [...prevState.myArray, {"name": "object"}]
}))

将对象推送到数组的开头

this.setState(prevState => ({
  myArray: [ {"name": "object"}, ...prevState.myArray]
}))

1
我用这个答案。它也适用于添加到数组中:this.setState((prevState) => ({ myArray: [values, ...prevState.myArray], }));
Gus,

1
这比接受的答案好得多,并且按照React文档的建议进行。
伊恩·J·米勒

2
之所以肯定+1,是因为其他答案未遵循最新的准则(如果状态本身发生了变化,则使用回调)。
马特·弗莱彻

如何在状态数组中添加另一个数组对象?
Chandni

14

您根本不应该运行状态。至少不是直接。如果要更新阵列,则需要执行以下操作。

var newStateArray = this.state.myArray.slice();
newStateArray.push('new value');
this.setState(myArray: newStateArray);

直接在状态对象上工作是不可取的。您还可以查看React的不变性助手。

https://facebook.github.io/react/docs/update.html


5
我相信这个答案是正确的,尽管我很想知道为什么我们不能对状态进行操作,即为什么它是不可取的。经过一番挖掘后,我发现了以下React教程-为什么不可变是重要的,它有助于填写缺少的信息,并且该教程还用于.slice()创建新数组并保留不可变性。谢谢您的帮助。
BebopSong

11

您可以使用.concat方法使用新数据创建数组的副本:

this.setState({ myArray: this.state.myArray.concat('new value') })

但要注意.concat传递数组时方法的特殊行为- [1, 2].concat(['foo', 3], 'bar')会导致[1, 2, 'foo', 3, 'bar']


1

该代码对我有用:

fetch('http://localhost:8080')
  .then(response => response.json())
  .then(json => {
  this.setState({mystate: this.state.mystate.push.apply(this.state.mystate, json)})
})

3
欢迎使用Stack Overflow!请不要只回答源代码。尝试提供有关您的解决方案如何工作的很好的描述。请参阅:我如何写一个好的答案?。谢谢
sɐunıɔןɐqɐp

我尝试了这个,但无济于事。这是我的代码fetch(`api.openweathermap.org/data/2.5/forecast?q=${this.searchBox.value + KEY} `) .then( response => response.json() ) .then( data => { this.setState({ reports: this.state.reports.push.apply(this.state.reports, data.list)}); });
henrie

我首先将状态初始化为一个空数组,即this.state = { reports=[] }... pls我想知道我在做什么错
henrie '19

@Hamid Hosseinpour
henrie

1

React-Native

如果您还希望您的UI(即您的flatList)是最新的,请使用PrevState:在下面的示例中,如果用户单击该按钮,它将向列表(在模型和UI中)添加一个新对象)

data: ['shopping','reading'] // declared in constructor
onPress={() => {this.setState((prevState, props) => {
return {data: [new obj].concat(prevState.data) };
})}}. 

0

通过以下方式,我们可以检查和更新对象

this.setState(prevState => ({
    Chart: this.state.Chart.length !== 0 ? [...prevState.Chart,data[data.length - 1]] : data
}));

0

在这里,您不能将对象推入这样的状态数组。您可以按自己的方式在常规数组中进行推送。在这里,您必须设置状态,

this.setState({ 
     myArray: [...this.state.myArray, 'new value'] 
})

-1

如果您只是想像这样更新状态

   handleClick() {
        this.setState(
{myprop: this.state.myprop +1}
        })
    }

考虑这种方法

   handleClick() {
        this.setState(prevState => {
            return {
                count: prevState.count + 1
            }
        })
    }

基本上prevState正在为我们编写this.state。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.