Maneira correta de empurrar para a matriz de estado

122

Parece que estou tendo problemas para enviar dados para uma matriz de estado. Estou tentando conseguir desta forma:

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

Mas acredito que essa é a forma incorreta e causa problemas com mutabilidade?

Ilja
fonte

Respostas:

145

Array push retorna comprimento

this.state.myArray.push('new value')retorna o comprimento da matriz estendida, em vez da própria matriz. Array.prototype.push () .

Eu acho que você espera que o valor retornado seja a matriz.

Imutabilidade

Parece que é mais o comportamento de React:

NUNCA modifique this.state diretamente, pois chamar setState () depois pode substituir a mutação que você fez. Trate this.state como se fosse imutável. React.Component .

Eu acho que você faria assim (não estou familiarizado com React):

var joined = this.state.myArray.concat('new value');
this.setState({ myArray: joined })
Márton Tamás
fonte
1
Quando eu faço console.log(this.state.myArray), é sempre um atrás. Alguma ideia do porquê?
Si8 de
@ Si8 Bem, infelizmente não uso muito o React. Mas os documentos dizem: setState()enfileira as alterações no estado do componente e informa ao React que esse componente e seus filhos precisam ser renderizados novamente com o estado atualizado. Acho que não foi atualizado naquele momento, logo após configurá-lo. Você poderia postar um exemplo de código, onde possamos ver qual ponto você está configurando e registrando, por favor?
Márton Tamás
Obrigado pela resposta. É assíncrono, por isso não mostrará as alterações imediatamente. No entanto, setState tem um retorno de chamada que exibiu o valor correto. Obrigado novamente.
Si8
w3schools.com/jsref/jsref_concat_array.asp concatena dois arrays (não array e string), .concat('new value'); deveria ser .concat(['new value']);
Manohar Reddy Poreddy
1
@ManoharReddyPoreddy Valores não matriciais são perfeitamente válidos para o concat()método. Veja: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ( Matrizes e / ou valores para concatenar em uma nova matriz. )
Márton Tamás
176

Usando es6, pode ser feito assim:

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

Spread syntax

Aliaksandr Sushkevich
fonte
1
Eu fiz o mesmo, há dois casos em que meuArray pode ter valores e não terá. então nisso, se já tem valores, funciona perfeitamente bem. Mas em nenhum dado ... não atualiza o estado com 'novo valor'. Qualquer soln?
Krina Soni
Deve funcionar com qualquer array, não importa se tem valores ou não, será desestruturado de qualquer maneira. Talvez haja algo errado em outro lugar. Você poderia mostrar um exemplo do seu código?
Aliaksandr Sushkevich
oi Por favor, consulte meu comentário em @Tamas answer. Foi apenas uma amostra no console. Eu tentei meu array: [... this.state.myArray, 'novo valor'] para atualizar meu array de estado. Mas ele concatra apenas o último valor. Você poderia me dizer a solução?
Johncy
@Johncy Não tenho certeza se o seu problema está relacionado a esta pergunta, tente fazer uma pergunta separada e descrever o comportamento esperado e tentarei ajudá-lo.
Aliaksandr Sushkevich
5
De acordo com a documentação do React: "Como this.propse this.statepode ser atualizado de forma assíncrona, você não deve confiar em seus valores para calcular o próximo estado." No caso de modificar uma matriz, uma vez que a matriz já existe como uma propriedade de this.statee você precisa referenciar seu valor para definir um novo valor, você deve usar a forma de setState()que aceita uma função com o estado anterior como argumento. Exemplo: this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] }));Veja: reactjs.org/docs/…
Bungle
103

Nunca recomendado para alterar o estado diretamente.

A abordagem recomendada em versões posteriores do React é usar uma função de atualização ao modificar estados para evitar condições de corrida:

Empurre a string para o final da matriz

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

Empurre a string para o início da matriz

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

Empurre o objeto para o final da matriz

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

Empurre o objeto para o início da matriz

this.setState(prevState => ({
  myArray: [ {"name": "object"}, ...prevState.myArray]
}))
Hemadri Dasari
fonte
1
Eu usei essa resposta. Também funciona para prefixar na matriz:this.setState((prevState) => ({ myArray: [values, ...prevState.myArray], }));
Gus
1
esta é uma abordagem muito melhor do que a resposta aceita e funciona da maneira que a documentação do React recomenda.
Ian J Miller
2
Definitivamente marcar isso com +1 porque as outras respostas não seguem as diretrizes mais recentes de uso de retornos de chamada em caso de mutação de estado consigo mesmo.
Matt Fletcher
como adicionar outros objetos de array em array de estado?
Chandni,
14

Você não deveria operar o estado de forma alguma. Pelo menos não diretamente. Se você quiser atualizar seu array, você vai querer fazer algo assim.

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

Trabalhar no objeto de estado diretamente não é desejável. Você também pode dar uma olhada nos ajudantes de imutabilidade do React.

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

Christoph
fonte
5
Acredito que essa resposta seja a correta, embora eu gostaria de saber por que não podemos operar no estado, ou seja, por que não é desejável. Após pesquisar um pouco, encontrei o seguinte tutorial React - Why Immutability is Important , que ajudou a preencher as informações que faltavam e o tutorial também usa .slice()para criar um novo array e preservar a imutabilidade. Obrigado pela ajuda.
BebopSong
11

Você pode usar o .concatmétodo para criar uma cópia de sua matriz com novos dados:

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

Mas cuidado com o comportamento especial do .concatmétodo ao passar matrizes - [1, 2].concat(['foo', 3], 'bar')resultará em [1, 2, 'foo', 3, 'bar'].

Ginden
fonte
1

Este Código funciona para mim:

fetch('http://localhost:8080')
  .then(response => response.json())
  .then(json => {
  this.setState({mystate: this.state.mystate.push.apply(this.state.mystate, json)})
})
Hamid Hosseinpour
fonte
3
Bem-vindo ao Stack Overflow! Por favor, não responda apenas com o código-fonte. Tente fornecer uma boa descrição sobre como sua solução funciona. Veja: Como escrevo uma boa resposta? . Obrigado
sɐunıɔ ןɐ qɐp
Eu tentei isso, mas sem sucesso. Aqui está o meu 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
e inicialmente inicializei o estado como uma matriz vazia, ou seja this.state = { reports=[] }... por favor, gostaria de saber o que estou fazendo de errado
henrie
@Hamid Hosseinpour
henrie
1

React-Native

se você também quiser que sua UI (ou seja, sua flatList) esteja atualizada, use PrevState: no exemplo abaixo, se o usuário clicar no botão, ele adicionará um novo objeto à lista (tanto no modelo quanto na UI )

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

Da seguinte forma, podemos verificar e atualizar os objetos

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

Aqui você não pode empurrar o objeto para uma matriz de estado como esta. Você pode empurrar como seu caminho na matriz normal. Aqui você deve definir o estado,

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

Se você está apenas tentando atualizar o estado assim

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

Considere esta abordagem

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

Basicamente, prevState está escrevendo this.state para nós.

senhor ninguém
fonte