Почему мне нужно дважды щелкнуть, чтобы событие сработало? - PullRequest
1 голос
/ 14 июля 2020

Извините за простоту этого вопроса, я новичок в React. Я построил калькулятор с двумя полями ввода и кнопками для выполнения различных расчетов. Теперь я превращаю его в более полнофункциональный калькулятор с целой клавиатурой. В моем коде, приведенном ниже, я почти уверен, что проблема заключается в том, как написана функция onClick, но я не уверен, как она должна быть написана. (большая часть кода в образце связана с начальным проектом и не имеет отношения к этому вопросу, я просто хотел включить весь компонент для хорошей оценки.)

Когда я нажимаю на «1 ", консоль регистрирует 1 в первый раз, но 1 вверху страницы не отображается до второго щелчка. Что у меня здесь происходит, что не позволяет отображать один вверху, пока я не нажму кнопку «1» во второй раз?

Первый щелчок: Приложение после первого щелчка по 1

Второй щелчок: Приложение после второго щелчка по 1

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.setNum1 = this.setNum1.bind(this);
    this.setNum2 = this.setNum2.bind(this);
    this.add = this.add.bind(this);
    this.subtract = this.subtract.bind(this);
    this.multiply = this.multiply.bind(this);
    this.divide = this.divide.bind(this);
    this.clear = this.clear.bind(this);
    this.buttonPressed = this.buttonPressed.bind(this);

    this.state = {
      pressed: "",
      result: "",
      num1: "",
      num2: "",
    };
  }

  buttonPressed(e) {
    e.preventDefault();
    const pressed = e.target.name;
    const result = this.state.pressed;
    this.setState({ pressed });
    this.setState({ result });
    console.log(e.target.name);
  }

  setNum1(e) {
    const num1 = e.target.value ? parseInt(e.target.value) : "";
    this.setState({ num1 });
  }

  setNum2(e) {
    const num2 = e.target.value ? parseInt(e.target.value) : "";
    this.setState({ num2 });
  }

  add(e) {
    e.preventDefault();
    const result = this.state.num1 + this.state.num2;
    this.setState({ result });
  }

  subtract(e) {
    e.preventDefault();
    const result = this.state.num1 - this.state.num2;
    this.setState({ result });
  }

  multiply(e) {
    e.preventDefault();
    const result = this.state.num1 * this.state.num2;
    this.setState({ result });
  }

  divide(e) {
    e.preventDefault();
    const result = this.state.num1 / this.state.num2;
    this.setState({ result });
  }

  clear(e) {
    e.preventDefault();
    this.setState({ num1: "", num2: "", result: 0 });
  }

  render() {
    const { num1, num2, result } = this.state;
    return (
      <div>
        <h1>{this.state.result}</h1>
        <input onChange={this.setNum1} value={num1}></input>
        <input onChange={this.setNum2} value={num2}></input>
        <br />
        <button name="1" onClick={this.buttonPressed}>
          1
        </button>
        <button onClick={this.add}>+</button>
        <button onClick={this.subtract}>-</button>
        <button onClick={this.multiply}>x</button>
        <button onClick={this.divide}>/</button>
        <button onClick={this.clear}>clear</button>
      </div>
    );
  }
}

export default Calculator;

Если кто-нибудь может помочь мне узнать, что мне нужно сделать, чтобы исправить эту ситуацию, я был бы очень признателен!

Ответы [ 2 ]

2 голосов
/ 14 июля 2020

Проблема здесь в

 buttonPressed(e) {
    e.preventDefault();
    // here e.target.name is 1 so value in const pressed becomes 1
    const pressed = e.target.name;
    // currently this.state.pressed is "" so result becomes "" if you want to show
    // first number as result use const result = e.target.name
    const result = this.state.pressed;
    this.setState({ pressed });
    this.setState({ result });
    console.log(e.target.name);
  }

Вы устанавливаете свой результат на this.state.pressed, который пуст в первый раз, поэтому он устанавливает результат как пустую строку, но во второй раз как this.state .pressed равен 1, поэтому он устанавливает результат как 1, поэтому он отображается при втором щелчке

0 голосов
/ 14 июля 2020

Обоснование:

  • Блок, вызывающий проблему

    buttonPressed(e) {
      e.preventDefault();
      const pressed = e.target.name;
      const result = this.state.pressed;
      this.setState({ pressed });
      this.setState({ result });
      console.log(e.target.name);
    }
    
  • Причина: setState будет в то время как для обновления значений объекта состояния (т.е.) setState не обновляет объект состояния немедленно, поскольку его асинхронный c по своей природе.

  • ссылка: Почему React setState / useState не обновить немедленно - блог

Возможные варианты решения этой проблемы перечислены ниже

Случай A: установка 'результат' объект состояния на основе объекта состояния «нажат»

  • Примечание: установка состояния другого объекта после изменения состояния целевого объекта с помощью функции обратного вызова

  • Цель: установить объект состояния «результат» только после того, как был установлен объект состояния «нажата»

  • Реализация: после установки состояния «нажата» мы выполняем функцию обратного вызова для установить объект состояния «результат»

  • Синтаксис:

    this.setState (setTarg etStateObject, function () {// выполнение действий, которые должны быть выполнены после завершения setTargetStateObject});

  • Решение:

     buttonPressed(e) {
       e.preventDefault();
       const pressed = e.target.name;
       this.setState({ pressed }, function() {
         this.setState({ result: this.state.pressed });
       });
     }
    

Случай B: установка объекта состояния результата на основе переданного значения аргумента 'e'

  • Решение:

    buttonPressed(e) {
      e.preventDefault();
      const pressed = e.target.name;
      // const result = this.state.pressed;
    
      // directly assign the 'e' arg value to the result const variable
      const result = pressed;
    
      // 'result' state object is not dependent on 'pressed' state object
      this.setState({ pressed });
      this.setState({ result });
      console.log(e.target.name);
    }
    

Примечание: Я бы посоветовал вам использовать Функциональный компонент , так как вы можете иметь чистый код с меньшим количеством строк, использовать недавно представленные хуки от команды React, проще писать тесты и многое другое. это также важно для производительности.

Создал эту песочницу для вас Calculator pgm - класс vs функциональный компонент реакции - вы можете увидеть, как ваша программа будет реализована в Класс против функциональных компонентов.

Ссылки:

...