React: как исправить ошибку «array.push не является функцией», которая возникает только после попытки очистить состояние?

#javascript #html #reactjs

#javascript #HTML #reactjs

Вопрос:

В этом калькуляторе React Javascript есть функция, которая помещает операторы в массив, чтобы длину массива можно было использовать для ограничения количества десятичных знаков, разрешенных в числе, до одной десятичной точки на оператор. Оператор может быть немедленно введен успешно после сброса браузера, но не после clear нажатия кнопки. Любая помощь будет с благодарностью принята.

index.js

 import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';

const initState = {
  text: '0',
  operators:[' ']
}

class JavascriptCalculator extends React.Component {

  constructor(props) {
    super(props);
    this.state = initState;
    this.display = this.display.bind(this);
    this.clear = this.clear.bind(this);
    this.calculate = this.calculate.bind(this);
  }

  display(text){
    // if display is zero, remove the leading zero from the text.
    if(this.state.text == 0){
      this.state.text = '';
    }

    let regex = /[*/ -]/;

    // if text is not an operator
    if (!regex.test(text)){

      let displayed = this.state.text

      // start by adding text
      displayed  = text;

      // disallow multiple decimal points in a number
      // if attempt at more than one decimal point remove last one.
      let array = displayed.split('');
      let count = 0;
      for (let i = 0; i < array.length; i  ){
        if (array[i] === '.'){
          count  ;
        }
      }
      // one decimal point is allowed per operator.
      // thus to allow the first decimal point,
      // this.state.operators must be initialized
      // to length of 1.
      if(count > this.state.operators.length){
        array.pop();
      }

      displayed = array.join('');

      this.setState({ text: displayed});
    }

    // if text is an operator
    if (regex.test(text)){

      // add the text to the array
      // so that repeated decimal points are prevented
      let array = this.state.operators;
      array.push(text);
      this.setState({ operators: array});

      let displayed = this.state.text

      displayed  = text;
      this.setState({ text: displayed});
    }

    // if text is equals sign, run the calculate function.
    if (text === '='){
      let displayed = this.state.text.split('');
      displayed.push('=');
      console.log(displayed);
      this.calculate(displayed);
    }
  }

  calculate(displayed){
    let regex = /[*/ -]/;
    let text = '';
    let length = displayed.length;
    let operators = [];

    //console.log(this.state.array);

    // capture numbers longer than one digit by adding them to a string
    // and adding a comma in place of the operators, so the string
    // can be split into an array at the operators.
    for (let i = 0; i < length; i  ){
      // put numbers into a string
      if (displayed[i].match(/[d.]/)) {
        text =displayed[i];
      }
      // add commas to string in place of operators
      if (displayed[i].match(regex)){
        text =',';
        // add operators to their own array
        operators.push(displayed[i]);
      }
      if (displayed[i] === '='){
        break;
      }
    }

    //console.log(operators);
    // create the numbers array
    let numbers = text.split(',');
    //console.log(numbers);

    // initialize answer with first number
    let answer = numbers[0];
    let func = undefined;

    // Start with second number
    for (let i = 1; i < numbers.length; i  ){

      func = returnFunc(operators.shift());
      answer = func(answer, numbers[i]);
      this.setState({text: answer})
    }

    function returnFunc(val) {
      switch (val) {
        case ' ':
        return function sum(a,b) { return Number(a) Number(b)};
        case '-':
        return function subtract(a,b) { return Number(a)-Number(b)};
        case '*':
        return function multiply(a,b) { return Number(a)*Number(b)};
        case '/':
        return function divide(a,b) { return Number(a)/Number(b)};
        default:
        throw new Error("Called with unknown operator "   val);
      }
    }
  }

  clear(){
    this.setState({text:'0', operators:' '});
  }

  render() {
    return (
      <div id="javascript-calculator">
      <h1 id="title">Javascript Calculator</h1>
      <div id="display">{this.state.text}</div>
      <hr/>
      <div>
      <button id="clear" onClick={e => this.clear()}> clear </button>
      <button id="equals" onClick={e => this.display("=")}> = </button>
      <button id="zero" onClick={e => this.display("0")}> 0 </button>
      <button id="one" onClick={e => this.display("1")}> 1 </button>
      <button id="two" onClick={e => this.display("2")}> 2 </button>
      <button id="three" onClick={e => this.display("3")}> 3 </button>
      <button id="four" onClick={e => this.display("4")}> 4 </button>
      <button id="five" onClick={e => this.display("5")}> 5 </button>
      <button id="six" onClick={e => this.display("6")}> 6 </button>
      <button id="seven" onClick={e => this.display("7")}> 7 </button>
      <button id="eight" onClick={e => this.display("8")}> 8 </button>
      <button id="nine" onClick={e => this.display("9")}> 9 </button>
      <button id="add" onClick={e => this.display(" ")}>   </button>
      <button id="subtract" onClick={e => this.display("-")}> - </button>
      <button id="multiply" onClick={e => this.display("*")}> * </button>
      <button id="divide" onClick={e => this.display("/")}> / </button>
      <button id="decimal" onClick={e => this.display(".")}> . </button>
      </div>
      </div>
    );
  }
}

ReactDOM.render(<JavascriptCalculator />, document.getElementById("app"));
  

index.html

 <!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>Javascript Calculator</title>
  <style>
  </style>
</head>
<body>
  <main>
    <div id="app"></app>
    </main>
  </script>
  </body>
  </html>
  

Ответ №1:

Когда вы запускаете свою clear функцию,

 clear(){
                                       // You set it to a string here
    this.setState({text:'0', operators:' '});
}
  

вы меняете свое operators состояние с массива на строку

Измените его на это

 clear(){
                                   // add the braces here
    this.setState({text:'0', operators:[' ']});
}
  

Или, как упоминал Мохаммад Фейсал, вы можете установить его initState следующим образом

 clear(){
    this.setState(initState);
}
  

Ответ №2:

В вашем коде ошибка. вы забыли добавить [ ] в свою функцию setState

вместо того, чтобы делать это

 clear(){
    this.setState({text:'0', operators:' '});
  }
  

Сделайте это

 clear(){
    this.setState(initState);
  }
  

Ответ №3:

clear функция устанавливает operators значение , а не значение [' '] .

Правильным решением было бы:

 clear(){
    this.setState({text:'0', operators:[' ']});
}