vanyahuk
@vanyahuk

Почему render выполняеться перед componentWillMount?

есть компонента:

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from "redux";
import FilterModels from './FilterModels';
import {getTypes} from '../../actions/AjaxDataActions';

class FilterForm extends Component {

	constructor(props) {

		super(props);

	}

	async componentWillMount(){

               console.log( 1 );
		await this.props.getTypes(this.props.params, this.props.api) ;
		console.log( 2 );

	}


	render() {

		console.log( 3 )

		return (
			<div>
				<FilterModels/>
			</div>
		)
	}
}

function matchDispatchToProps(dispatch) {

	return bindActionCreators({
		getTypes: getTypes
	}, dispatch);
}

export default connect(
	state => ({
		api: state.api,
		params: state.ajaxData
	}), matchDispatchToProps)(FilterForm);


код action:
export const getTypes = (object, api) => {
	return async dispatch => {
		await axios.post(api.url + api.transports + '/' + api.type)
			.then(response => {
				dispatch({
					type: UPDATE_AJAX_PARAMS,
					payload: response.data
				});
			});
	}

};


по идеи console.log должен рисовать 1->2->3, а на практике - 1,3,2

Вопрос - что не так с кодом и как исправить?
  • Вопрос задан
  • 560 просмотров
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Потому что библиотека не ожидает возвращаемое значение в componentWillMount и следом сразу вызывает render.
Забудьте этот метод - он не рекомендован к использованию. Как уже писали выше, асинхронные запросы рекомендуется инициировать в componentDidMount. Он выполняется после вызова render, который вы по какой-то неясной причине хотите избежать.

Вот два варианта решения:
1. До загрузки данных возвращать в render null или прелоадер.
render() {
   const { data } = this.props;

   if (!data) return null;
     
    return (
      <div>
        <FilterModels />
      </div>
    )
  }
}

2. Переместить загрузку данных в родительский компонент и отрисовывать целевой по условию:
render() {
  const { filterData } = this.props;
  return (
    <Wrapper>
      {filterData  && <FilterForm data={filterData} />}
   </Wrapper>
  )
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
trofProg
@trofProg
Fullstack developer (Typescript / Python)
Загрузку по апи лучше делать в componentDidMount, и менять стэйты в нем, об этом можно почитать в документации https://reactjs.org/docs/react-component.html#comp... . componentWillMont уже является deprecated, вместо него можно все выполнять в конструкторе (дифанить стэйты и биндить функции). Логи выполняются правильно. Если бы ты прокидывал пропсы в компонент и они бы изменились, то 3 выполнилось бы ещё раз. Если бы отрисовка компонента ожидала загрузку по апи, то мы бы долго ждали пока появится компонент. Компонент появляется без задержки, просто потом перерисовывается, если меняются состояния, которые он использует
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы