状態配列にプッシュする正しい方法


122

データを状態配列にプッシュする際に問題が発生しているようです。私はそれをこの方法で達成しようとしています:

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

しかし、これは間違った方法であり、可変性の問題を引き起こすと思いますか?

回答:


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)するとき、それは常に後ろにあります。なぜだと思いますか?
Si8

@ Si8残念ながら、Reactはあまり使いません。しかし、ドキュメントは言う: setState()コンポーネントの状態への変更をエンキューし、Reactにこのコンポーネントとその子を更新された状態で再レンダリングする必要があることを伝えます。 そのため、設定直後はまだ更新されていないようです。コードの例を投稿していただけませんか。どこに設定してログに記録しているかを確認できますか?
マートンタマシュ

ご返信ありがとうございます。非同期であるため、変更はすぐには表示されません。ただし、setStateには正しい値を表示するコールバックがあります。再度、感謝します。
Si8

w3schools.com/jsref/jsref_concat_array.aspの 連結は、2つの配列(アレイではない文字列)、連結し .concat('new value'); なければならない .concat(['new value']);
ManoharさんレディPoreddy

1
@ManoharReddyPoreddy非配列値はconcat()メソッドに対して完全に有効です。参照:developer.mozilla.org/en-US/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が値を持つことができる場合と持たない場合の2つの場合があります。そのため、すでに値がある場合は、完全に正常に機能します。しかし、データがない場合、状態は「新しい値」で更新されません。どんなソルン?
Krina Soni 2018

これは、任意の配列で機能するはずです。値があるかどうかに関係なく、とにかく解体されます。他の場所に問題があるのか​​もしれません。あなたのコードの例を見せていただけませんか?
Aliaksandr Sushkevich 2018

こんにちは@タマスの回答の下で私のコメントを参照してください。これはコンソールの単なるサンプルでした。myArray:[... this.state.myArray、 'new value']を試して状態配列を更新しましたが、最後の値のみが連結されます。解決策を教えていただけませんか?
ジョンシー2018

@Johncy問題がこの質問に関連しているかどうかはわかりません。別の質問をして、予想される動作を説明してください。お手伝いします。
Aliaksandr Sushkevich

5
パードキュメントに反応:「のでthis.propsthis.state非同期で更新することができる、あなたは次の状態を計算するため、それらの値に依存しないでください。」配列を変更する場合、配列はのプロパティとして既に存在し、this.stateその値を参照して新しい値を設定する必要があるためsetState()、以前の状態の関数を引数として受け入れるの形式を使用する必要があります。例:this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] }));参照:reactjs.org/docs/...
バングル

103

状態を直接変更することはお勧めしません。

後のバージョンのReactで推奨されるアプローチは、競合状態を防ぐために状態を変更するときに更新関数を使用することです。

文字列を配列の最後にプッシュします

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のドキュメントで推奨されている方法で行われます。
Ian J Miller

2
他の回答はそれ自体で状態を変更する場合にコールバックを使用する最新のガイドラインに従っていないため、これを間違いなく+1します。
Matt Fletcher、

状態配列に別の配列オブジェクトを追加する方法は?
チャンドニー

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 2018

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)}); });
ヘンリー

そして、私は最初に空の配列として状態を初期化しましたthis.state = { reports=[] }。つまり... pls私は私が間違っていることを知りたいです
ヘンリー

@Hamid Hosseinpour
ヘンリー

1

リアクトネイティブ

uもUI(つまりur 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を書き込んでいます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.