Корректная модификация массивов состояний в ReactJS



Я хочу добавить элемент в конец state массив, это правильный способ сделать это?



this.state.arrayvar.push(newelement);
this.setState({arrayvar:this.state.arrayvar});


Я обеспокоен тем, что изменения массива на месте с push может вызвать проблемы - это безопасно?



альтернатива создания копии массива, и setStateing это кажется расточительным.

554   6  

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

    Ничего не найдено.