Durum dizisine itmenin doğru yolu


122

Verileri bir durum dizisine aktarmada sorunlar yaşıyorum. Bunu şu şekilde başarmaya çalışıyorum:

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

Ama bunun yanlış bir yol olduğuna ve değişkenlikle ilgili sorunlara neden olduğuna inanıyorum.

Yanıtlar:


146

Dizi itme uzunluğu döndürür

this.state.myArray.push('new value')dizinin kendisi yerine genişletilmiş dizinin uzunluğunu döndürür. Array.prototype.push () .

Sanırım döndürülen değerin dizi olmasını bekliyorsunuz.

Değişmezlik

Görünüşe göre daha çok React'in davranışı:

Bu.state'i ASLA doğrudan değiştirmeyin, çünkü daha sonra setState () çağrısı yaptığınız mutasyonun yerini alabilir. Bunu, değişmezmiş gibi ele alın. React.Component .

Sanırım, bunu şu şekilde yapardınız (React'e aşina değilsiniz):

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

1
Ben yaptığımda console.log(this.state.myArray)her zaman arkamda olur. Herhangi bir fikrin neden?
Si8

@ Si8 Maalesef çok fazla React kullanmıyorum. Ancak dokümanlar şunu söylüyor: setState()Bileşen durumundaki değişiklikleri sıralar ve React'e bu bileşenin ve alt bileşenlerinin güncellenmiş durumla yeniden oluşturulması gerektiğini söyler. Sanırım, ayarladıktan hemen sonra o anda güncellenmiyor. Lütfen hangi noktayı ayarladığınızı ve kaydettiğinizi görebileceğimiz bir kod örneği gönderebilir misiniz?
Márton Tamás

Cevabınız için teşekkürler. Eşzamansız olduğundan değişiklikleri hemen göstermez. Ancak setState, doğru değeri gösteren bir geri aramaya sahip. Tekrar teşekkürler.
Si8

w3schools.com/jsref/jsref_concat_array.asp, iki diziyi birleştirir (dizi ve dize değil), .concat('new value'); olmalıdır .concat(['new value']);
Manohar Reddy Poreddy

1
@ManoharReddyPoreddy Dizi olmayan değerler concat()yöntem için mükemmel şekilde geçerlidir . Bakınız: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ( Yeni bir diziye birleştirilecek diziler ve / veya değerler. )
Márton Tamás

176

Es6 kullanarak şu şekilde yapılabilir:

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

Yayılmış sözdizimi


1
Ben de aynısını yaptım, myArray'in değerlere sahip olabileceği iki durum var ve olmayacak. böylece zaten değerleri varsa, mükemmel şekilde çalışır. Ancak hiçbir veride .. durumu 'yeni değer' ile güncellemez. Herhangi bir soln?
Krina Soni

Herhangi bir diziyle çalışmalı, değerlere sahip olup olmaması önemli değil, yine de yok edilecek. Belki başka bir yerde bir sorun vardır. Lütfen kodunuzun bir örneğini gösterir misiniz?
Aliaksandr Sushkevich

merhaba Lütfen @Tamas cevabının altındaki yorumuma bakın. Sadece konsolda bir örnekti. Durum dizimi güncellemek için myArray: [... this.state.myArray, 'yeni değer'] denedim.Ama sadece son değeri birleştiriyor.Çözümü bana söyleyebilir misiniz?
Johncy

@Johncy Sorununuzun bu soruyla ilgili olup olmadığından emin değilim, ayrı bir soru sorup beklenen davranışı anlatmaya çalışın, size yardımcı olmaya çalışacağım.
Aliaksandr Sushkevich

5
React belgelerine göre: "Çünkü this.propsve this.stateeşzamansız olarak güncellenebilir, bir sonraki durumu hesaplarken onların değerlerine güvenmemelisiniz." Bir diziyi değiştirme durumunda, dizi zaten bir özelliği olarak mevcut olduğundan this.stateve yeni bir değer ayarlamak için onun değerine başvurmanız gerektiğinden setState(), önceki durumu bağımsız değişken olarak kabul eden bir işlevi kullanmalısınız . Örnek: this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] }));Bkz: reactjs.org/docs/…
Bungle

104

Devletin doğrudan mutasyona uğratılması asla tavsiye edilmez

Sonraki React sürümlerinde önerilen yaklaşım, yarış koşullarını önlemek için durumları değiştirirken bir güncelleme işlevi kullanmaktır:

Dizeyi dizinin sonuna itin

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

Dizeyi dizinin başına it

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

Nesneyi dizinin sonuna it

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

Nesneyi dizinin başına it

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

1
Bu cevabı kullandım. Aynı zamanda dizinin başına eklemek için de çalışır:this.setState((prevState) => ({ myArray: [values, ...prevState.myArray], }));
Gus

1
bu, kabul edilen cevaptan çok daha iyi bir yaklaşım ve React belgelerinin önerdiği şekilde mi?
Ian J Miller

2
Bunu kesinlikle + 1'leme çünkü diğer yanıtlar, durumu kendiliğinden değiştiriyorsa geri aramaları kullanmanın en son kurallarına uymuyor.
Matt Fletcher

durum dizisine başka bir dizi nesnesi nasıl eklenir?
Chandni

14

Eyaleti hiç işletmemelisiniz. En azından doğrudan değil. Dizinizi güncellemek istiyorsanız, bunun gibi bir şey yapmak isteyeceksiniz.

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

Doğrudan durum nesnesi üzerinde çalışmak arzu edilmez. React'in değişmezlik yardımcılarına da göz atabilirsiniz.

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


5
Bu cevabın doğru olduğuna inanıyorum, ancak neden devlet üzerinde çalışamayacağımızı, yani neden arzu edilmediğini bilmek isterdim. Biraz araştırma yaptıktan sonra, aşağıdaki React eğitimini buldum - Neden Değişmezlik Önemli , bu eksik bilgileri doldurmaya yardımcı oldu ve eğitim ayrıca .slice()yeni bir dizi oluşturmak ve değişmezliği korumak için de kullanıyor . Yardım için teşekkürler.
BebopSong

11

.concatDizinizin kopyasını yeni verilerle oluşturmak için yöntemi kullanabilirsiniz :

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

Ancak .concatdizileri iletirken yöntemin özel davranışına dikkat edin - [1, 2].concat(['foo', 3], 'bar')sonuç olacaktır [1, 2, 'foo', 3, 'bar'].


1

Bu Kod benim için çalışıyor:

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'a hoş geldiniz! Lütfen sadece kaynak kodu ile cevap vermeyin. Çözümünüzün nasıl çalıştığı hakkında güzel bir açıklama sağlamaya çalışın. Bakınız: Nasıl iyi bir cevap yazabilirim? . Teşekkürler
sɐunıɔ ןɐ qɐp

Bunu denedim ama boşuna. İşte kodumfetch(`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

ve ilk olarak durumu boş bir dizi olarak başlattım yani this.state = { reports=[] }... lütfen neyi yanlış yaptığımı bilmek isterim
henrie

@Hamid Hosseinpour
henrie

1

Tepki-Yerli

Kullanıcı arayüzünüzün de (ör. ur flatList) güncel olmasını istiyorsanız, PrevState'i kullanın: aşağıdaki örnekte kullanıcı düğmeyi tıklarsa, listeye yeni bir nesne ekleyecektir (hem modelde hem de kullanıcı arayüzünde )

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

0

Aşağıdaki şekilde nesneleri kontrol edip güncelleyebiliriz

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

0

Burada nesneyi böyle bir durum dizisine itemezsiniz. Normal dizide kendi yolunuz gibi itebilirsiniz. Burada durumu ayarlamalısın,

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

-1

Sadece durumu böyle güncellemeye çalışıyorsanız

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

Bu yaklaşımı düşünün

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

Temelde prevState this.state'i bizim için yazıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.