Отладчики Chrome, Firefox не отображают правильное значение «this» в приложении реагирования - PullRequest
0 голосов
/ 28 ноября 2018

Вот небольшой фрагмент кода в классе реагирующих компонентов (который создается с помощью CRA 2)

  click = () => {
    console.log(this, "hello");
    let x = 1 + 1; //This is just here to let chrome put a break point here. 
  }

Когда этот код выполняется, он напечатает объект компонента на консоли.

Однако - если я присоединю отладчик к этой точке, и Chrome (68), и Firefox (63) покажут 'this' как неопределенное.

Что здесь происходит?

Это как-то связано с плагином babel transform-class-properties, который используется для создания клика как свойства класса?

Редактировать: Да, похоже, именно так и есть.

Если мы вручную свяжем метод как:

  constructor() {
    super();
    this.click2 = this.click2.bind(this);
  }

  click2() {
    console.log(this, "hello");
    let x = 1 + 1;
  }

, тогда он будет работать нормально.

В любом случае - есть ли удобный способ решить эту проблему, поэтому мне не нужно помещать все эти операторы связывания?

Ответы [ 3 ]

0 голосов
/ 07 декабря 2018

Я думаю, вам нужно установить параметры babel, чтобы отключить обработку модуля.См. Этот ответ:

Как не допустить, чтобы babel перевела 'this' в 'undefined'

В вашем .babelrc:

{
  "presets": [
    [ "es2015", { "modules": false } ]
  ]
}
0 голосов
/ 13 декабря 2018

Прагматичная альтернатива - если то, что вы хотите сделать, это проверить состояние / свойства реактивного компонента в определенной точке, это ввести точку останова в соответствии с нормой - но вместо использования отладчика для проверки состояния- использовать плагин реагировать на инструменты , чтобы реально проверить состояние.

Это может показаться немного странным, но это вариант.

0 голосов
/ 02 декабря 2018

Я создал пример для CodeSandbox , который, по-моему, воспроизводит вашу проблему, хотя я не уверен.Пожалуйста, создайте свой собственный пример, если это не так.Соответствующий код приведен ниже.

В этом примере код работает нормально.console.log(this, "hello") регистрирует Square объект + "привет", как и следовало ожидать.Если вы поставите точку останова в строке let y = 2 + 2, отладчик Chrome покажет

this: undefined
x: 2
y: undefined

Конечно, y не определено, поскольку оператор let y еще не выполнен.x определяется, как и ожидалось.this не определено, потому что Реакт и Вавилон прыгают через множество обручей под прикрытием, а this фактически не определено.Если вы хотите получить доступ к this из отладчика, вам нужно использовать _this.На самом деле, даже если вы ставите точку останова в строке let y = 2 + 2, это не фактический источник, который выполняется или где находится точка останова.То, что вы видите, - это удобство, обеспечиваемое исходной картой , которая позволяет вам просматривать и устанавливать точку останова для написанного вами кода, несмотря на тот факт, что фактический код, который выполняется, совершенно другой (результат обработки Babelтак далее.).

Код, который я написал:

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null
    };
  }

  click = () => {
    console.log(this, "hello");
    let x = 1 + 1; //This is just here to let chrome put a break point here.
    let y = 2 + 2; //This is just here to let chrome put a break point here.
  };

  render() {
    return (
      <button className="square" onClick={this.click}>
        {this.props.value}
      </button>
    );
  }
}

код, который фактически выполняется:

var Square =
/*#__PURE__*/
function (_React$Component) {
  (0, _inherits2.default)(Square, _React$Component);

  function Square(props) {
    var _this;

    (0, _classCallCheck2.default)(this, Square);
    _this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(Square).call(this, props));
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "click", function () {
      console.log((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "hello");
      var x = 1 + 1; //This is just here to let chrome put a break point here.

      var y = 2 + 2; //This is just here to let chrome put a break point here.
    });
    _this.state = {
      value: null
    };
    return _this;
  }

  (0, _createClass2.default)(Square, [{
    key: "render",
    value: function render() {
      return _react.default.createElement("button", {
        className: "square",
        onClick: this.click
      }, this.props.value);
    }
  }]);
  return Square;
}(_react.default.Component);

Из-за внутренних элементов React.js (в частности, из-заоборачивает события), к моменту вызова обработчика this не определено.Если вы посмотрите на стек вызовов, то увидите, что executeDispatch вызывает invokeGuardedCallbackAndCatchFirstError с явным значением undefined для объекта context, которое в конечном итоге является значением this внутри обратного вызова.React и Babel пытаются скрыть все это от вас, когда вы пишете код, но они не могут полностью скрыть это от отладчика, особенно в отношении this, поэтому в этом случае вам нужно перейти к реальному коду, чтобы увидеть, что вынужно сослаться на _this в отладчике.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...