Ответ 1
Возможно, вам придется лучше понимать асинхронное поведение javascript. Async означает "не ждать". То, что задача будет происходить в фоновом режиме и другой код будет продолжать выполняться. Хороший способ справиться с этим - установить состояние вашего компонента. Например, когда вы вводите componentDidMount
установите для состояния loading
значение true
. Затем, когда ваша асинхронная функция завершится, установите для этого состояния значение false
. В вашей функции render
вы можете либо отобразить сообщение "loading...", либо данные.
Вот некоторый код, который показывает упрощенный пример выборки асинхронных данных и того, как вы могли бы справиться с этим в React. Откройте инструменты разработчика в своем браузере и посмотрите на вывод консоли, чтобы лучше понять жизненный цикл React.
РЕДАКТИРОВАТЬ: Код был обновлен для использования новых рекомендаций жизненного цикла React по состоянию на апрель 2018. Таким образом, я заменил componentWillMount
на более безопасный componentDidMount
.
Может показаться неэффективным обновлять состояние после того, как компонент уже смонтирован, как правильно подразумевает "монтирование DID компонента". Однако, согласно официальной документации React для componentDidMount:
"Если вам нужно загрузить данные из удаленной конечной точки, это хорошее место для создания сетевого запроса".
"Вызов setState()
в этом методе вызовет дополнительный рендеринг, но это произойдет до того, как браузер обновит экран. Это гарантирует, что даже если в этом случае render()
будет вызван дважды, пользователь не увидит промежуточное состояние. "
Вот полный пример кода:
class MyComponent extends React.Component {
constructor(props) {
super();
console.log('This happens 1st.');
this.state = {
loading: 'initial',
data: ''
};
}
loadData() {
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('This happens 6th (after 3 seconds).');
resolve('This is my data.');
}, 3000);
});
console.log('This happens 4th.');
return promise;
}
componentDidMount() {
console.log('This happens 3rd.');
this.setState({ loading: 'true' });
this.loadData()
.then((data) => {
console.log('This happens 7th.');
this.setState({
data: data,
loading: 'false'
});
});
}
render() {
if (this.state.loading === 'initial') {
console.log('This happens 2nd - after the class is constructed. You will not see this element because React is still computing changes to the DOM.');
return <h2>Intializing...</h2>;
}
if (this.state.loading === 'true') {
console.log('This happens 5th - when waiting for data.');
return <h2>Loading...</h2>;
}
console.log('This happens 8th - after I get data.');
return (
<div>
<p>Got some data!</p>
<p>{this.state.data}</p>
</div>
);
}
}
ReactDOM.render(
<MyComponent />,
document.getElementsByClassName('root')[0]
);
И вот рабочий пример на CodePen.
Наконец, я думаю, что этот образ современного жизненного цикла React, созданный сопровождающим React Даном Абрамовым, полезен для визуализации того, что происходит и когда.
ВНИМАНИЕ, что по состоянию на React 16.4, этот жизненный цикл схема имеет небольшую неточность: getDerivedStateFromProps
теперь также называется после setState
, а также forceUpdate
. См. Эту статью в официальном блоге React об исправлении для getDerivedStateFromProps
Эта интерактивная версия диаграммы жизненного цикла React, созданной Wojciech Maj, позволяет вам выбрать версию React> 16.04 с последним поведением (все еще с точностью до React 16.8.6, 27 марта 2019 г.). Обязательно установите флажок "Показывать менее распространенные жизненные циклы".