butteff
@butteff
Раз в тысячу лет заправляю свитер в носки

Почему метод класса не подхватывает нужные данные в states, если вызвать его из конструктора?

Есть компонент с конструктором, который выглядит так:

class Day extends Component {
  constructor(props) {
    super(props);
    this.state = {
      calories: 0,
      fat: 0,
      protein: 0,
      carbs: 0,
    };

    this.caloriesCalculate();
  }


Есть метод caloriesCalculate(). Он выглядит так:
caloriesCalculate() {
    
    var fat = 0;
    var protein = 0;
    var carbs = 0;
    var calories = 0;

    const { dataArray, mealPlan, date } = this.props;
    const { products } = dataArray;

    var timestamp = date._i/1000;
    Object.keys(mealPlan[timestamp]).map(function(type) {
      var product = products[mealPlan[timestamp][type]];
      fat += product.fat/1000;
      protein += product.protein/1000;
      carbs += product.carb/1000;
      calories += product.calories/1000;
    });

    var nutritions = {
      calories: calories,
      fat: fat,
      protein: protein,
      carbs: carbs,
    }

    this.setState(nutritions);
  }


Метод работает правильно, когда я привязываю его к нажатию на кнопку:
onClick={() => this.caloriesCalculate()}

Но если он запущен из конструктора, все равно states имеют значения нулей.
При этом, если делать console.log(nutritions);, то в консоли он показывает правильные значения, однако данные внутри render() - нули.

В render() вот что:

<li className='day-calories'><b>Calories:</b> {calories}, <b>Fat:</b> {fat}g, <b>Protein:</b> {protein}g, <b>Carbs:</b> {carbs}g</li>


Передавать значения в конструктор из props компонента - это делать те же расчеты в родительском компоненте.
Можно проделать расчеты и вконструкторе - но тогда я всё равно дважды использую один и тот же код ( onClick={() => this.caloriesCalculate()} не для отладки и тестов, а нужный метод, т.е. просто перенести все расчеты в конструктор - не выход).

Что я делаю не так?
Почему this.calculateCalories() не подхватывает нужные данные в states из конструктора?
  • Вопрос задан
  • 54 просмотра
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
В calculateCalories вместо вызова setState следует возвращать вычисленное состояние:
class Day extends React.Component {
  state = this.calculateCalories();

  calculateCalories() {
    /* ... */
    return {
      calories,
      fat,
      protein,
      carbs,
    };
  }

  handleClick = () => {
    this.setState(this.calculateCalories());
  };
  
  render() {
    ...
  }
}


Еще почитайте про статический метод getDerivedStateFromProps. Возможно подойдет.

Ну и если не подразумевается изменение состояния, то нет особого смысла туда писать данные, их можно использовать напрямую из props.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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