Корректная модификация массивов состояний в ReactJS
Я хочу добавить элемент в конец state массив, это правильный способ сделать это?
this.state.arrayvar.push(newelement);
this.setState({arrayvar:this.state.arrayvar});
Я обеспокоен тем, что изменения массива на месте с push может вызвать проблемы - это безопасно?
альтернатива создания копии массива, и setStateing это кажется расточительным.
6 ответов:
The React docs говорит:
этому относиться.состояние, как если бы оно было неизменным.
код
pushбудет мутировать состояние напрямую, и это потенциально может привести к коду, подверженному ошибкам, даже если вы "сбрасываете" состояние снова после этого. Например, это может привести к тому, что некоторые методы жизненного цикла, какcomponentDidUpdateне сработают.рекомендуемый подход в более поздних версиях React заключается в использовании updater
простой, если вы используете
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] }))
React может выполнять пакетные обновления, и поэтому правильным подходом является предоставление setState функции, которая выполняет обновление.
для аддона React update надежно работает следующее:
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, выведите в качестве примера того, что произойдет, если вы ошибетесь.
вызов 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 упоминается в комментарии, Вы можете использовать react неизменность помощников. Я нашел это очень полезным.
документы:
простым нажатием
var initialArray = [1, 2, 3]; var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]initialArray по-прежнему [1, 2, 3].
этот код работает для меня:
fetch('http://localhost:8080') .then(response => response.json()) .then(json => { this.setState({mystate: this.state.mystate.push.apply(this.state.mystate, json)}) })
Comments