Modo corretto per eseguire il push nell'array di stato


122

Mi sembra di avere problemi a inserire i dati in un array di stato. Sto cercando di ottenerlo in questo modo:

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

Ma credo che questo sia un modo errato e causi problemi con la mutabilità?

Risposte:


145

Il push di array restituisce la lunghezza

this.state.myArray.push('new value')restituisce la lunghezza dell'array esteso, invece dell'array stesso. Array.prototype.push () .

Immagino che ti aspetti che il valore restituito sia l'array.

Immutabilità

Sembra che sia piuttosto il comportamento di React:

NON modificare MAI this.state direttamente, poiché chiamare setState () in seguito potrebbe sostituire la mutazione che hai fatto. Tratta this.state come se fosse immutabile. React.Component .

Immagino che lo faresti in questo modo (non ho familiarità con React):

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

1
Quando lo faccio console.log(this.state.myArray)è sempre uno dietro. Qualche idea sul perché?
Si8

@ Si8 Beh, sfortunatamente non uso troppo React. Ma i documenti dicono: setState()accoda le modifiche allo stato del componente e dice a React che questo componente e i suoi figli devono essere nuovamente renderizzati con lo stato aggiornato. Quindi immagino che non sia aggiornato in quel momento subito dopo averlo impostato. Potresti postare un esempio di codice, dove possiamo vedere quale punto stai impostando e registrando, per favore?
Márton Tamás

Grazie per la risposta. È asincrono, quindi non ti mostrerà subito le modifiche. Tuttavia setState ha un callback che mostrava il valore corretto. Grazie ancora.
Si8

w3schools.com/jsref/jsref_concat_array.asp concat concatena due array (non array e stringa), .concat('new value'); dovrebbe essere .concat(['new value']);
Manohar Reddy Poreddy

1
@ManoharReddyPoreddy I valori non array sono perfettamente validi per il concat()metodo. Vedere: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ( Array e / o valori da concatenare in un nuovo array. )
Márton Tamás

176

Usando es6 può essere fatto in questo modo:

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

Diffondere la sintassi


1
Ho fatto lo stesso, ci sono due casi in cui myArray può avere valori e non lo farà. quindi in questo, se ha già valori, funziona perfettamente. Ma in nessun dato..non aggiorna lo stato con 'nuovo valore'. Qualche soln?
Krina Soni

Dovrebbe funzionare con qualsiasi array, non importa se ha valori o meno, sarà comunque destrutturato. Forse c'è qualcosa che non va in un altro posto. Potresti mostrare un esempio del tuo codice?
Aliaksandr Sushkevich

ciao Si prega di fare riferimento al mio commento sotto la risposta di @Tamas. Era solo un campione in console. Ho provato myArray: [... this.state.myArray, 'new value'] per aggiornare il mio array di stato. Ma concentra solo l'ultimo valore. Potresti dirmi la soluzione?
Johncy

@ Johncy Non sono sicuro che il tuo problema sia correlato a questa domanda, prova a fare una domanda separata e descrivi il comportamento previsto e cercherò di aiutarti.
Aliaksandr Sushkevich

5
Secondo i documenti di React: "Poiché this.propse this.statepossono essere aggiornati in modo asincrono, non dovresti fare affidamento sui loro valori per calcolare lo stato successivo." Nel caso di modifica di un array, poiché l'array esiste già come proprietà di this.stateed è necessario fare riferimento al suo valore per impostare un nuovo valore, è necessario utilizzare la forma di setState()che accetta una funzione con lo stato precedente come argomento. Esempio: this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] }));Vedi: reactjs.org/docs/…
Bungle

104

Mai consigliato di mutare lo stato direttamente.

L'approccio consigliato nelle versioni successive di React consiste nell'usare una funzione di aggiornamento quando si modificano gli stati per evitare condizioni di competizione:

Spinge la stringa alla fine dell'array

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

Spinge la stringa all'inizio dell'array

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

Spinge l'oggetto alla fine dell'array

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

Spinge l'oggetto all'inizio dell'array

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

1
Ho usato questa risposta. Funziona anche per anteporre all'array:this.setState((prevState) => ({ myArray: [values, ...prevState.myArray], }));
Gus

1
questo è un approccio molto migliore rispetto alla risposta accettata e lo fa nel modo raccomandato dalla documentazione di React.
Ian J Miller,

2
Sicuramente facendo +1 perché le altre risposte non seguono le ultime linee guida sull'utilizzo dei callback se mutano lo stato con se stesso.
Matt Fletcher

come aggiungere un altro array di oggetti in array di stato?
Chandni

14

Non dovresti assolutamente gestire lo stato. Almeno, non direttamente. Se vuoi aggiornare il tuo array, ti consigliamo di fare qualcosa di simile.

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

Lavorare direttamente sull'oggetto stato non è desiderabile. Puoi anche dare un'occhiata agli aiutanti dell'immutabilità di React.

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


5
Credo che questa risposta sia quella corretta anche se mi sarebbe piaciuto sapere perché non possiamo operare sullo stato, cioè perché non è desiderabile. Dopo un po 'di ricerca ho trovato il seguente tutorial di React - Perché l'immutabilità è importante , che ha aiutato a compilare le informazioni mancanti e il tutorial utilizza anche .slice()per creare un nuovo array e preservare l'immutabilità. Grazie per l'aiuto.
BebopSong

11

Puoi utilizzare il .concatmetodo per creare una copia del tuo array con nuovi dati:

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

Ma attenzione al comportamento speciale del .concatmetodo quando si passano gli array: [1, 2].concat(['foo', 3], 'bar')risulterà in [1, 2, 'foo', 3, 'bar'].


1

Questo codice funziona per me:

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

3
Benvenuto in Stack Overflow! Per favore, non rispondere solo con il codice sorgente. Prova a fornire una bella descrizione su come funziona la tua soluzione. Vedi: come scrivo una buona risposta? . Grazie
sɐunıɔ ןɐ qɐp

Ho provato questo ma inutilmente. Ecco il mio codicefetch(`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

e in primo luogo ho inizializzato lo stato come un array vuoto cioè this.state = { reports=[] }... per favore mi piacerebbe sapere cosa sto sbagliando
henrie

@Hamid Hosseinpour
henrie

1

React-Native

se vuoi che anche la tua UI (es. ur flatList) sia aggiornata, usa PrevState: nell'esempio seguente se l'utente fa clic sul pulsante, aggiungerà un nuovo oggetto all'elenco (sia nel modello che nell'interfaccia utente )

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

0

Nel modo seguente possiamo controllare e aggiornare gli oggetti

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

0

Qui non è possibile eseguire il push dell'oggetto in un array di stato come questo. Puoi spingere come preferisci nel normale array. Qui devi impostare lo stato,

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

-1

Se stai solo cercando di aggiornare lo stato in questo modo

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

Considera questo approccio

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

Fondamentalmente prevState sta scrivendo this.state per noi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.