Forma correcta de empujar a la matriz de estado


122

Parece que tengo problemas para enviar datos a una matriz de estado. Estoy tratando de lograrlo de esta manera:

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

Pero creo que esta es una forma incorrecta y causa problemas con la mutabilidad.

Respuestas:


145

Longitud de retorno de inserción de matriz

this.state.myArray.push('new value')devuelve la longitud de la matriz extendida, en lugar de la matriz en sí. Array.prototype.push () .

Supongo que espera que el valor devuelto sea la matriz.

Inmutabilidad

Parece que es más bien el comportamiento de React:

NUNCA mutes this.state directamente, ya que llamar a setState () después puede reemplazar la mutación que hiciste. Trate este estado como si fuera inmutable. React.Componente .

Supongo que lo harías así (no familiarizado con React):

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

1
Cuando lo hago console.log(this.state.myArray), siempre hay uno detrás. ¿Alguna idea de por qué?
Si8

@ Si8 Bueno, desafortunadamente no uso demasiado React. Pero los documentos dicen: setState()pone en cola los cambios en el estado del componente y le dice a React que este componente y sus hijos deben volver a renderizarse con el estado actualizado. Así que supongo que no se actualiza en ese momento justo después de configurarlo. ¿Podría publicar un ejemplo de código, donde podamos ver qué punto lo está configurando y registrando, por favor?
Márton Tamás

Gracias por la respuesta. Es asincrónico, por lo que no le mostrará los cambios de inmediato. Sin embargo, setState tiene una devolución de llamada que mostró el valor correcto. Gracias de nuevo.
Si8

w3schools.com/jsref/jsref_concat_array.asp concat concatena dos matrices (no matriz y cadena), .concat('new value'); debería ser .concat(['new value']);
Manohar Reddy Poreddy

1
@ManoharReddyPoreddy Los valores que no son de matriz son perfectamente válidos para el concat()método. Ver: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ( Matrices y / o valores para concatenar en una nueva matriz. )
Márton Tamás

176

Usando es6 se puede hacer así:

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

Sintaxis de propagación


1
Hice lo mismo, hay dos casos en que myArray puede tener valores y no los tendrá. así que, si ya tiene valores, funciona perfectamente bien. Pero en ningún dato ... no actualiza el estado con 'nuevo valor'. ¿Alguna solución?
Krina Soni

Debería funcionar con cualquier arreglo, no importa si tiene valores o no, se desestructurará de todos modos. Quizás haya algo mal en otro lugar. ¿Podría mostrar un ejemplo de su código?
Aliaksandr Sushkevich

hola Por favor, consulte mi comentario en la respuesta de @Tamas. Era solo una muestra en consola. Intenté myArray: [... this.state.myArray, 'nuevo valor'] para actualizar mi matriz de estado. Pero concate solo el último valor. ¿Podría por favor decirme la solución?
Johncy

@Johncy No estoy seguro de si su problema está relacionado con esta pregunta, intente hacer una pregunta separada y describa el comportamiento esperado e intentaré ayudarlo.
Aliaksandr Sushkevich

5
Según los documentos de React: "Debido a que this.propsy this.statepuede actualizarse de forma asincrónica, no debe confiar en sus valores para calcular el siguiente estado". En el caso de modificar una matriz, dado que la matriz ya existe como una propiedad de this.statey necesita hacer referencia a su valor para establecer un nuevo valor, debe usar la forma de setState()que acepta una función con el estado anterior como argumento. Ejemplo: this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] }));Ver: reactjs.org/docs/…
Bungle

104

Nunca se recomendó mutar el estado directamente.

El enfoque recomendado en versiones posteriores de React es usar una función de actualización al modificar estados para evitar condiciones de carrera:

Empuje la cuerda hasta el final de la matriz

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

Empuje la cadena al comienzo de la matriz

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

Empuje el objeto hasta el final de la matriz

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

Empuje el objeto al comienzo de la matriz

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

1
Usé esta respuesta. También funciona para anteponer en la matriz:this.setState((prevState) => ({ myArray: [values, ...prevState.myArray], }));
Gus

1
Este es un enfoque mucho mejor que la respuesta aceptada y lo hace de la manera que recomienda la documentación de React.
Ian J Miller

2
Definitivamente haciendo +1 en esto porque las otras respuestas no siguen las últimas pautas de uso de devoluciones de llamada si mutan el estado consigo mismo.
Matt Fletcher

¿Cómo agregar otros objetos de matriz en la matriz de estado?
Chandni

14

No deberías estar operando el estado en absoluto. Al menos, no directamente. Si desea actualizar su matriz, querrá hacer algo como esto.

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

No es deseable trabajar directamente en el objeto de estado. También puede echar un vistazo a los ayudantes de inmutabilidad de React.

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


5
Creo que esta respuesta es la correcta, aunque me hubiera gustado saber por qué no podemos operar sobre el estado, es decir, por qué no es deseable. Después de investigar un poco, encontré el siguiente tutorial de React: Por qué la inmutabilidad es importante , que ayudó a completar la información que faltaba y el tutorial también se utiliza .slice()para crear una nueva matriz y preservar la inmutabilidad. Gracias por la ayuda.
BebopSong

11

Puede usar el .concatmétodo para crear una copia de su matriz con nuevos datos:

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

Pero tenga cuidado con el comportamiento especial del .concatmétodo al pasar matrices: [1, 2].concat(['foo', 3], 'bar')resultará en [1, 2, 'foo', 3, 'bar'].


1

Este código funciona para mí:

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

3
¡Bienvenido a Stack Overflow! No responda solo con el código fuente. Intente proporcionar una descripción agradable sobre cómo funciona su solución. Ver: ¿Cómo escribo una buena respuesta? . Gracias
sɐunıɔ ןɐ qɐp

Intenté esto pero fue en vano. Aquí está mi códigofetch(`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

y en primer lugar inicialicé el estado como una matriz vacía, es decir this.state = { reports=[] }... por favor, me gustaría saber qué estoy haciendo mal
henrie

@Hamid Hosseinpour
henrie

1

Reaccionar nativo

Si también desea que su UI (es decir, su flatList) esté actualizada, use PrevState: en el siguiente ejemplo, si el usuario hace clic en el botón, agregará un nuevo objeto a la lista (tanto en el modelo como en la UI )

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

0

De la siguiente forma podemos comprobar y actualizar los objetos

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

0

Aquí no puede empujar el objeto a una matriz de estado como esta. Puede empujar a su manera en una matriz normal. Aquí tienes que configurar el estado,

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

-1

Si solo estás tratando de actualizar el estado así

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

Considere este enfoque

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

Básicamente, prevState está escribiendo this.state para nosotros.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.