Cara yang benar untuk mendorong ke array negara

122

Sepertinya saya mengalami masalah saat mendorong data ke dalam array status. Saya mencoba untuk mencapainya dengan cara ini:

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

Tapi saya yakin ini adalah cara yang salah dan menyebabkan masalah dengan mutabilitas?

Ilja
sumber

Jawaban:

145

Array push mengembalikan panjangnya

this.state.myArray.push('new value')mengembalikan panjang dari array yang diperpanjang, bukan dari array itu sendiri. Array.prototype.push () .

Saya kira Anda mengharapkan nilai yang dikembalikan menjadi array.

Kekekalan

Sepertinya ini lebih seperti perilaku React:

JANGAN PERNAH mutasi this.state secara langsung, karena memanggil setState () setelahnya dapat menggantikan mutasi yang Anda buat. Perlakukan negara ini seolah-olah tidak dapat diubah. React.Component .

Saya kira, Anda akan melakukannya seperti ini (tidak terbiasa dengan React):

var joined = this.state.myArray.concat('new value');
this.setState({ myArray: joined })
Márton Tamás
sumber
1
Ketika saya melakukannya console.log(this.state.myArray), selalu ada yang tertinggal. Tahu kenapa?
Si8
@ Si8 Sayangnya, saya tidak menggunakan React terlalu banyak. Tetapi dokumen mengatakan: setState()enqueues berubah ke status komponen dan memberi tahu React bahwa komponen ini dan turunannya perlu dirender ulang dengan status yang diperbarui. Jadi saya kira itu tidak diperbarui pada saat itu tepat setelah mengaturnya. Bisakah Anda memposting contoh kode, di mana kami dapat melihat titik mana yang Anda atur dan masuk?
Márton Tamás
Terima kasih atas tanggapannya. Ini asinkron sehingga tidak akan langsung menampilkan perubahan. Namun setState memang memiliki callback yang menampilkan nilai yang benar. Terima kasih lagi.
Si8
w3schools.com/jsref/jsref_concat_array.asp menggabungkan dua array (bukan array dan string), .concat('new value'); harus .concat(['new value']);
Manohar Reddy Poreddy
1
@ManoharReddyPoreddy Nilai non-array benar-benar valid untuk concat()metode ini. Lihat: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ( Array dan / atau nilai untuk digabungkan ke dalam array baru. )
Márton Tamás
176

Menggunakan es6 bisa dilakukan seperti ini:

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

Sebarkan sintaks

Aliaksandr Sushkevich
sumber
1
Saya melakukan hal yang sama, ada dua kasus myArray dapat memiliki nilai dan tidak. sehingga, jika sudah memiliki nilai, ia bekerja dengan baik. Tetapi tidak ada data..itu tidak memperbarui status dengan 'nilai baru'. Ada soln?
Krina Soni
Itu harus bekerja dengan array apa pun, tidak masalah apakah itu memiliki nilai atau tidak itu akan dihancurkan. Mungkin ada yang salah di tempat lain. Bisakah Anda menunjukkan contoh kode Anda?
Aliaksandr Sushkevich
hai Silakan lihat komentar saya di bawah jawaban @Tamas. Itu hanya sampel di konsol. Saya mencoba myArray: [... this.state.myArray, 'new value'] untuk mengupdate state array. Tapi itu hanya menggabungkan nilai terakhir. Tolong beritahu saya solusinya?
Johncy
@Johncy Saya tidak yakin apakah masalah Anda terkait dengan pertanyaan ini, coba ajukan pertanyaan terpisah dan jelaskan perilaku yang diharapkan dan saya akan mencoba membantu Anda.
Aliaksandr Sushkevich
5
Menurut dokumen React: "Karena this.propsdan this.statedapat diperbarui secara asinkron, Anda tidak boleh mengandalkan nilainya untuk menghitung status selanjutnya." Dalam kasus memodifikasi larik, karena larik sudah ada sebagai properti this.statedan Anda perlu mereferensikan nilainya untuk menyetel nilai baru, Anda harus menggunakan bentuk setState()yang menerima fungsi dengan status sebelumnya sebagai argumen. Contoh: this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] }));Lihat: reactjs.org/docs/…
Bungle
104

Tidak pernah disarankan untuk mengubah status secara langsung.

Pendekatan yang direkomendasikan dalam versi React yang lebih baru adalah dengan menggunakan fungsi pembaru saat memodifikasi status untuk mencegah kondisi balapan:

Dorong string ke akhir larik

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

Dorong string ke awal larik

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

Dorong objek ke akhir larik

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

Dorong objek ke awal larik

this.setState(prevState => ({
  myArray: [ {"name": "object"}, ...prevState.myArray]
}))
Hemadri Dasari
sumber
1
Saya menggunakan jawaban ini. Ini juga bekerja untuk prepending ke dalam array:this.setState((prevState) => ({ myArray: [values, ...prevState.myArray], }));
Gus
1
ini adalah pendekatan yang jauh lebih baik daripada jawaban yang diterima dan melakukannya seperti yang direkomendasikan dokumentasi React.
Ian J Miller
2
Jelas memberi ini +1 karena jawaban lain tidak mengikuti pedoman terbaru dalam menggunakan panggilan balik jika status mutasi dengan sendirinya.
Matt Fletcher
bagaimana cara menambahkan objek array lain dalam array negara?
Chandni
14

Anda seharusnya tidak mengoperasikan negara sama sekali. Setidaknya, tidak secara langsung. Jika Anda ingin memperbarui larik Anda, Anda akan ingin melakukan sesuatu seperti ini.

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

Mengerjakan objek negara secara langsung tidak diinginkan. Anda juga dapat melihat pembantu keabadian React.

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

Christoph
sumber
5
Saya percaya jawaban ini adalah yang benar meskipun saya ingin tahu mengapa kita tidak dapat beroperasi di negara bagian, yaitu mengapa itu tidak diinginkan. Setelah sedikit menggali, saya menemukan tutorial React berikut - Why Immutability is Important , yang membantu mengisi info yang hilang dan tutorial juga digunakan .slice()untuk membuat array baru dan menjaga keabadian. Terima kasih untuk bantuannya.
BebopSong
11

Anda dapat menggunakan .concatmetode untuk membuat salinan array Anda dengan data baru:

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

Tetapi berhati-hatilah terhadap perilaku khusus .concatmetode ketika melewati array - [1, 2].concat(['foo', 3], 'bar')akan menghasilkan [1, 2, 'foo', 3, 'bar'].

Ginden
sumber
1

Kode ini bekerja untuk saya:

fetch('http://localhost:8080')
  .then(response => response.json())
  .then(json => {
  this.setState({mystate: this.state.mystate.push.apply(this.state.mystate, json)})
})
Hamid Hosseinpour
sumber
3
Selamat datang di Stack Overflow! Tolong jangan menjawab hanya dengan kode sumber. Cobalah untuk memberikan gambaran yang bagus tentang bagaimana solusi Anda bekerja. Lihat: Bagaimana cara menulis jawaban yang baik? . Terima kasih
sɐunıɔ ןɐ qɐp
Saya mencoba ini tetapi tidak berhasil. Ini kode sayafetch(`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
dan saya pertama kali menginisialisasi status sebagai array kosong yaitu this.state = { reports=[] }... tolong saya ingin tahu apa yang saya lakukan salah
henrie
@Hamid Hosseinpour
henrie
1

React-Native

jika Anda juga ingin UI Anda (mis. flatList Anda) diperbarui, gunakan PrevState: pada contoh di bawah ini jika pengguna mengklik tombol, itu akan menambahkan objek baru ke daftar (baik dalam model maupun UI )

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

Dengan cara berikut kita dapat memeriksa dan memperbarui objek

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

Di sini Anda tidak dapat mendorong objek ke array keadaan seperti ini. Anda dapat mendorong seperti cara Anda dalam larik normal. Di sini Anda harus mengatur negara,

this.setState({ 
     myArray: [...this.state.myArray, 'new value'] 
})
Sachin Muthumala
sumber
-1

Jika Anda hanya mencoba memperbarui status seperti itu

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

Pertimbangkan pendekatan ini

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

Pada dasarnya prevState menulis this.state untuk kita.

mister siapa
sumber