Вызвать setState после функции

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я знаю, что setState является асинхронным, но есть ли в любом случае (без Redux) возможность вызвать setState после выполнения другой функции ранее, как показано ниже:

 handleOpenUpdateItem = (item) => {
    const { getImageByItemId } = this.props;
    getImageByItemId(item.id);
    this.setState({ updateMode: true, item });
  };
  

Приветствую!

Комментарии:

1. Я думаю, getImageByItemId является асинхронным (или он содержит некоторые асинхронные функции)

2. Вы можете использовать promise в этой ситуации.

3. @PranavCBalan да, он подключен к redux и вызывает серверную часть

4. @Ernesto : переместите этот оператор this.setState({ updateMode: true, item }); в обратный вызов или используйте Promise

5. Я думаю, componentWillReceiveProps это идеальный хук для установки этого, state где можно быть уверенным, что state/prop обновлено..

Ответ №1:

Превратите свой handleOpenUpdateItem в async функцию. Затем вы можете написать синхронный код внутри нее.

   async handleOpenUpdateItem(item) {
       const { getImageByItemId } = this.props;
       const item = await getImageByItemId(item.id); // wait for the call to the backend to finish
       this.setState({ updateMode: true, item }); 
  };
  

Комментарии:

1. Наверное, я забыл упомянуть, что это асинхронная функция — getImageByItemId

2. @Ernesto не должно быть проблемой. Вы можете ожидать асинхронную функцию.

Ответ №2:

Как уже упоминалось в комментариях, вы могли бы использовать обратные вызовы, чтобы убедиться, что this.setState выполняется после завершения вашей функции (использование Promises или async/await тоже было бы отличным вариантом). Это пример того, как это может быть реализовано:

   getImageByItem = (id, callback) => {
    // Do something here
    // And return your image, or anything you want through callback like so:
    callback(yourImage)
  }

  handleOpenUpdateItem = (item) => {
    const { getImageByItemId } = this.props;
    getImageByItemId(item.id, (image) => {
      this.setState({ updateMode: true, item });
    });
  };
  

Итак, вы изменяете свою getImageByItem функцию, чтобы включить обратный вызов, а затем в handleOpenUpdateItem вы используете этот обратный вызов и setState внутри него.

РЕДАКТИРОВАТЬ ДЛЯ 2019

Поскольку @Levitator Disbалансирован, упомянутый ниже, вероятно, лучше использовать Promises , чтобы вы могли реализовать его следующим образом:

Без асинхронности / ожидания:

 getImageByItemId = (id) => {
  return new Promise((resolve, reject) => {
    // Do something with your id/image, then resolve
    resolve()
    // Or reject when some error happens
    reject()
  })
}

  handleOpenUpdateItem = (item) => {
    const { getImageByItemId } = this.props;
    getImageByItemId(id)
      .then(() => {
        this.setState({ updateMode: true, item });
      })
      .catch(() => {
        // ... handle your reject here
      })
  };
  

Или вы могли бы использовать async/await вот так:
Асинхронный / ожидающий:

 getImageByItemId = (id) => {
  return new Promise((resolve, reject) => {
    // Do something with your id/image, then resolve
    resolve()
    // Or reject when some error happens
    reject()
  })
}

handleOpenUpdateItem = async (item) => {
  const { getImageByItemId } = this.props;
  let something = await getImageByItemId(item.id)
  // or just:
  // await getImageByItemId(item.id)
  this.setState({ updateMode: true, item });
};
  

Комментарии:

1. да ладно, 2019 год наступил) Лучше использовать Promise 🙂

2. @Levitator Disbalance, ты абсолютно прав, виноват! Отредактировано, чтобы показать как обещание , так и асинхронность / ожидание 😉

Ответ №3:

this.setState() быть асинхронным означает, что вы не можете нормально выполнять что-то после этого и ожидать, что это произойдет только после завершения setState. Выполнение чего-либо до setState, а затем вызов setState (точно так же, как вы делали) будут работать из коробки.

Комментарии:

1. Это означает, что одна из функций перед ней (вероятно getImageById ) является asnyc, это не особенность setState() .

2. кроме того, как с этим бороться? Возможно, мне следует реорганизовать код … чтобы это изображение каким-то образом было присвоено элементу перед вызовом этого обработчика. Но я хотел получить элемент только для определенного элемента, не извлекать все элементы для всех элементов, видимых в списке.

Ответ №4:

Вы могли бы сделать handleOpenUpdateItem асинхронным и использовать await для getImageByItemId.

Комментарии:

1. у меня нет представителей для комментариев: S