Я хочу добавить элемент в конец массива state
, это правильный способ сделать это?
this.state.arrayvar.push(newelement);
this.setState({arrayvar:this.state.arrayvar});
Я обеспокоен тем, что изменение массива на месте с помощью push
может вызвать проблемы - безопасно?
Альтернатива создания копии массива и setState
ing, которая кажется расточительной.
Документы React говорят:
Относитесь к этому состоянию как к неизменному.
Ваше push
будет напрямую изменять состояние, что потенциально может привести к появлению кода, подверженного ошибкам, даже если впоследствии вы "сбрасываете" состояние снова. F.ex, это может привести к тому, что некоторые методы жизненного цикла, такие как componentDidUpdate
сработают.
Рекомендуемый подход в более поздних версиях React заключается в использовании функции обновления при изменении состояний для предотвращения состояний гонки:
this.setState(prevState => ({
arrayvar: [...prevState.arrayvar, newelement]
}))
"Трата" памяти не является проблемой по сравнению с ошибками, с которыми вы можете столкнуться при нестандартных модификациях состояния.
Альтернативный синтаксис для более ранних версий React
Вы можете использовать concat
для получения чистого синтаксиса, так как он возвращает новый массив:
this.setState({
arrayvar: this.state.arrayvar.concat([newelement])
})
В ES6 вы можете использовать Spread Operator:
this.setState({
arrayvar: [...this.state.arrayvar, newelement]
})
var a = [1,2,3, {a:1}]; var b = a.slice(); b[3].a = 2; console.log(a[3].a);
Самый простой, если вы используете ES6
.
initialArray = [1, 2, 3];
newArray = [ ...initialArray, 4 ]; // --> [1,2,3,4]
Новый массив будет [1,2,3,4]
чтобы обновить ваше состояние в Реагировать
this.setState({arrayvar:[...this.state.arrayvar, newelement]});
Самый простой способ с ES6
:
this.setState(prevState => ({
array: [...prevState.array, newElement]
}))
tableData = [['test','test']]
После того, как tableData = [['test','test'],['new','new']]
мой новый массив tableData = [['test','test'],['new','new']]
. как протолкнуть это @David и @Ridd
React может пакетно обновлять, и поэтому правильный подход заключается в предоставлении setState с функцией, которая выполняет обновление.
Для дополнения обновления React будет выполнено следующее:
this.setState( (state) => update(state, {array: {$push: [4]}}) );
или для concat():
this.setState( (state) => {
state.array = state.array.concat([4]);
return state;
});
Ниже показано, что https://jsbin.com/mofekakuqi/7/edit?js,output как пример того, что произойдет, если вы ошибетесь.
Приведение setTimeout() правильно добавляет три элемента, потому что React не будет выполнять пакетные обновления в обратном вызове setTimeout (см. https://groups.google.com/d/msg/reactjs/G6pljvpTGX0/0ihYw2zK9dEJ).
Багги onClick будут добавлять только "Третий", но фиксированный, добавит F, S и T, как ожидалось.
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'));
Как упоминается в примечании @nilgun, вы можете использовать помощники по неизменности. Я нашел, что это очень полезно.
Из документов:
Простой push
var initialArray = [1, 2, 3];
var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
initialArray все еще [1, 2, 3].
Если вы хотите использовать push, вы можете сделать что-то вроде этого:
// wrong because push modify the array directly
this.setState(prevState => ({
arrayvar: prevState.arrayvar.push(someElemet) && prevState.arrayvar,
}));
Лучшим решением, конечно, является предотвращение мутации с помощью concat, slice или spread.
Подробнее см. видеоурок.
Этот код работает для меня:
fetch('http://localhost:8080')
.then(response => response.json())
.then(json => {
this.setState({mystate: this.state.mystate.push.apply(this.state.mystate, json)})
})