#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 });
в обратный вызов или используйте Promise5. Я думаю,
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