React puede realizar actualizaciones por lotes y, por lo tanto, el enfoque correcto es proporcionar a setState una función que realice la actualización.
Para el complemento React update, lo siguiente funcionará de manera confiable:
this.setState( state => update(state, {array: {$push: [4]}}) );
o para concat ():
this.setState( state => ({
array: state.array.concat([4])
}));
A continuación se muestra lo que https://jsbin.com/mofekakuqi/7/edit?js,output como un ejemplo de lo que sucede si se equivoca.
La invocación setTimeout () agrega correctamente tres elementos porque React no procesará actualizaciones por lotes dentro de una devolución de llamada setTimeout (consulte https://groups.google.com/d/msg/reactjs/G6pljvpTGX0/0ihYw2zK9dEJ ).
El buggy onClick solo agregará "Third", pero el fijo agregará F, S y T como se esperaba.
class List extends React.Component {
constructor(props) {
super(props);
this.state = {
array: []
}
setTimeout(this.addSome, 500);
}
addSome = () => {
this.setState(
update(this.state, {array: {$push: ["First"]}}));
this.setState(
update(this.state, {array: {$push: ["Second"]}}));
this.setState(
update(this.state, {array: {$push: ["Third"]}}));
};
addSomeFixed = () => {
this.setState( state =>
update(state, {array: {$push: ["F"]}}));
this.setState( state =>
update(state, {array: {$push: ["S"]}}));
this.setState( state =>
update(state, {array: {$push: ["T"]}}));
};
render() {
const list = this.state.array.map((item, i) => {
return <li key={i}>{item}</li>
});
console.log(this.state);
return (
<div className='list'>
<button onClick={this.addSome}>add three</button>
<button onClick={this.addSomeFixed}>add three (fixed)</button>
<ul>
{list}
</ul>
</div>
);
}
};
ReactDOM.render(<List />, document.getElementById('app'));