Сумма массива Javascript сначала возвращает 0

Сильный кошмар, пытающийся вычислить сумму массива (чисел) в ReactJS / State.

Код, который я разместил ниже, работает, если я не использую состояние.

  1. По сути, через форму пользователь вводит число, а затем отправляет.
  2. То, что вводит пользователь, отслеживается через handleChangeEvent.
  3. А затем при handlSubmit число / значение сохраняется в this.state.donated и this.state.sum. Это массивы.

Когда я смотрю на консоль, оба состояния хранят массив чисел. И собирать каждую запись в массив нормально.

Я хочу найти и распечатать сумму этих чисел. Итак, я использую:

// FUNCTION TO CALCULATE TOTAL DONATIONS
const numbers = this.state.sum;
function add(a, b) {
  return a + b;
}
// // TOTAL VALUE OF NUMBERS IN THE ARRAY
const cal = numbers.reduce(add, 0);
console.info('CALC', cal);

Однако проблема, с которой я столкнулся, заключается в том, что я отправляю, например, число 20. Функция суммы, консоль сначала регистрирует 0. Когда я ввожу второй номер, консоль регистрирует первое введенное мной число ...

Что я делаю неправильно? Вот мой полный / соответствующий код:

class App extends React.Component {

  constructor() {
   super();

   this.state = {
     number: '',
     donated: [],
     sum: [],
     total: 0
   };

  this.handleChangeEvent = this.handleChangeEvent.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
 // we need to bind otherwise this is undefined
 }


//HANDLE FUNCTIONS
 handleChangeEvent(e) {
   this.setState({ number: e.target.value }, () => 
   console.info('NUMBER', this.state.number));
 }

 handleSubmit(e) {
   e.preventDefault();
  this.setState({donated: this.state.donated.concat(this.state.number).map(Number)}, () => console.info('DONATED', this.state.donated));
 this.setState({sum: this.state.donated.concat(this.state.number).map(Number)}, () => console.info('SUM', this.state.sum));


 // FUNCTION TO CALCULATE TOTAL DONATIONS
 const numbers = this.state.sum;
  function add(a, b) {
  return a + b;
}

// TOTAL VALUE OF NUMBERS IN THE ARRAY
const cal = numbers.reduce(add, 0);
console.info('CALC', cal);


document.forms['id_form'].reset();
}

render() {

return (
  <main>
    <section className = "section">
      <h1 className = "is-size-2">DONATE FOR A GOOD CAUSE</h1>
      <ProgressBar donated = {this.state.donated} sum = {this.state.sum}/>
      <Form donated = {this.state.donated} handleChangeEvent = {this.handleChangeEvent} handleSubmit = {this.handleSubmit} />
    </section>
  </main>
);
}
}

ReactDOM.render(
<App />,
document.getElementById('root')
);

Пожалуйста, поделитесь полным кодом

Rehan Haider 28.05.2018 13:43

вы можете использовать этот шаблон, чтобы поделиться своим рабочим примером codepen.io/anon/pen/ERYXYg

Rehan Haider 28.05.2018 13:46

Обновите свой вопрос, добавив минимальный воспроизводимый пример, демонстрирующий проблему, в идеале работоспособный, используя Stack Snippets (кнопка панели инструментов [<>]). Фрагменты стека поддерживают React, включая JSX; вот как это сделать.

T.J. Crowder 28.05.2018 13:46

Я действительно не могу этого сделать? Я использовал несколько компонентов? Я не думаю, что смогу перестроить все приложение, используя эту ссылку ... Мне пришлось бы изменить свой код ...

Reena Verma 28.05.2018 13:57

Я обнаружил вашу проблему, setState - это асинхронная функция, она не меняет состояние сразу после ее вызова, и вы используете состояние сразу после вызова состояния набора, которое все еще содержит старые значения

Rehan Haider 28.05.2018 13:59
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

По официальному документация

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.

Используйте setState callBack для вычисления суммы, чтобы получить обновленные значения

this.setState({sum: this.state.donated.concat(this.state.number).map(Number)}, () => {
    console.info('SUM', this.state.sum);
    // FUNCTION TO CALCULATE TOTAL DONATIONS
    const numbers = this.state.sum;
    function add(a, b) {
        return a + b;
    }

    // TOTAL VALUE OF NUMBERS IN THE ARRAY
    const cal = numbers.reduce(add, 0);
    console.info('CALC', cal);


    document.forms['id_form'].reset();
});

или вы можете просто обновлять переменную суммы после каждой отправки нового значения. как это

setState({sum: this.state.sum + this.state.number, number: 0});

хорошо, спасибо, как лучше всего структурировать это в моем коде?

Reena Verma 28.05.2018 14:03

УДИВИТЕЛЬНЫЙ!!!!!! СПАСИБО ВАМ БОЛЬШОЕ!!!! Очень признателен за вашу помощь! Я знал, что это как-то связано с заказом. Оцените передачу знаний. И узнал что-то новое сегодня. Спасибо! : D

Reena Verma 28.05.2018 14:11

Другие вопросы по теме