@shaman60

Как правильно вызвать setState из разных методов?

В компоненте есть 2 метода: добавить и удалить. Я хочу сделать метод который обновляет item. Т.е. вначале ищем старый с такими же данными, удаляем его, а на его место вставляем новый (обновленный). Если делаю как на примере ниже, то item просто добавляется, без удаления. Как грамотно это реализовать ?
export default class App extends Component {
  state = {
    items: []
  };
  add = (item) => {
    this.setState({
        items: [...this.state.items, item]
    });
  };
  remove = (id) => {
    let newItem = this.state.favorites.slice();
    newList.splice(index, 1);
    this.setState( {
        items: newList
    });
  };
  updateItem = (id, item) => {
    item.text = 'blabla';
    this.remove(id);
    this.add(item);
  }
  // Дальше остальные методы, рендер итд...
}
  • Вопрос задан
  • 133 просмотра
Решения вопроса 2
iCoderXXI
@iCoderXXI
React.JS/FrontEnd developer
Дело в том, что setState меняет состояние не сразу после вызова (не синхронно), а когда-нибудь, поэтому неизвестно заранее, когда именно state будет реально изменени. Поэтому setState в качестве аргумента может принимать как объект так и функцию (коллбэк). И вот в этот самый коллбэк всегда передается текущее актуальное состояние. Поэтому твой код надо переписать как-то так:

export default class App extends Component {
  state = {
    items: []
  };

  add = (item) => {
    this.setState((state) => ({
        ...state,
        items: [...state.items, item]
    }));
  };

  remove = (id) => {
    this.setState((state) => 
      return {
        ...state,
        items: state.filter(item => item.id !== id),
      }
    );
  };

  updateItem = (id, item) => {
    item.text = 'blabla';
    this.remove(id);
    this.add(item);
  }
  // Дальше остальные методы, рендер итд...
}


Другой вариант - отвязать методы add и remove от this.state, и передавать им state непосредственно. И этот вариант более правильный, т.к. он более явный, кроме того каждый вызов setState потенциально ведет к перерендеру, что нежелательно.

Поэтому как-то так:

export default class App extends Component {
  state = {
    items: []
  };

  add = (state, item) => ({
    ...state,
    items: [...state.items, item]
  });

  remove = (state, id) => ({
    ...state,
    items: state.filter(item => item.id !== id),
  });

  updateItem = (id, item) => {
    item.text = 'blabla';
    this.setState(state =>  this.add(this.remove(state, id), item));
  }
  // Дальше остальные методы, рендер итд...
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Indacoin Москва
от 80 000 до 160 000 руб.
Acme Crypto Corp Нижний Новгород
от 120 000 до 200 000 руб.
23 марта 2019, в 17:57
2000 руб./за проект
23 марта 2019, в 16:34
700 руб./за проект
23 марта 2019, в 15:42
400 руб./в час