Невозможно прочитать «состояние» неопределенного

avatar
Ryan Cocuzzo
8 апреля 2018 в 00:48
58
1
0

Я пытался понять, почему этот код не привязывается к классу. Во всех случаях, когда свойства state не были определены, что я читал, это было связано с отсутствием следующей строки:

this.someFunction = this.someFunction.bind(this);



Но мой код включает эту строку для моих функций. Однако я делаю HTTP-запрос с обещаниями, которые, как я подозреваю, сбрасывают компилятор, несмотря на то, что код идентичен Axios example.
import React, { Component } from 'react';
import ReactDom from 'react-dom';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';
import { Jumbotron } from "react-bootstrap";
import { Button } from "react-bootstrap";
import { Parallax, Background } from 'react-parallax';
import Fox from './fox.jpg';
var BASE_URL =  "http://127.0.0.1:8080/";
var BIN_API = BASE_URL + "binter-info";

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      tradingFrom: '...',
      tradingTo: '...',
      result: '...'
    };
    this.retrieveValue = this.retrieveValue.bind(this);
    this.updateResult = this.updateResult.bind(this);
  }

  updateResult(str) {
    var self = this;
    if (str != null) {
      self.setState({
        result: str,
      });
    }
  }

  retrieveValue() {
    var self = this;
    console.log('App: retrieveValue executed...');
    let symbol = this.state.tradingTo + this.state.tradingFrom;
  //  Make Server Request
    axios.get(BIN_API, {
          params: {
              symbol: symbol,
          }
      }).then(function (response) {
    console.log("Good");
    //console.log(response);
    self.updateResult(response.data);
    console.log('this.state.result is now ' + this.state.result); // LINE 49
  }).catch(function (error) {
    console.log(error);         // LINE 51
    self.updateResult("ERROR");
    });
   }

  render() {
    return (
      <div className="App">
        <Parallax className='par'
      blur={6}
     bgImage={Fox}
      bgImageAlt="Fox"
      strength={200}
    >
      <h1>Welcome</h1>
      <div style={{ height: '200px' }} />
    </Parallax>
        <Jumbotron>
        <h2 className="App-Text">The following is a <strong>BETA_VERSION </strong>website.</h2>
        </Jumbotron>
        <Button className="App-Button" onClick={this.retrieveValue}> Retrieve Value </Button>
        <div className="TXTAREA">
          <p className="TA-p">{this.state.result}</p>
        </div>
        <Jumbotron>
        <h1 className="App-Text">but wait..</h1>
        </Jumbotron>
        <Jumbotron>
        <h1 className="App-Text">theres more!</h1>
        </Jumbotron>
      </div>
    );
  }
}

export default App;

Моя ошибка:

App.js:51 TypeError: Cannot read property 'state' of undefined
    at App.js:49
Источник
Dan
8 апреля 2018 в 01:06
1

Это весь ваш код? App.js:51 указывает на закрывающий </p> в вашем примере кода. Вы пропустили некоторые операторы импорта? Что на самом деле представляют собой строки 49 и 51 вашего кода?

Ryan Cocuzzo
8 апреля 2018 в 01:12
1

@DanPantry Теперь все есть, я пропустил импорт и функцию render ранее, потому что не думал, что это важно, но теперь строки должны совпадать

Ответы (1)

avatar
Dan
8 апреля 2018 в 01:03
2

Ваша ошибка возникает из-за того, что вы вызываете this.state внутри обратного вызова Promise от Axios. this будет undefined.

console.log('this.state.result is now ' + this.state.result);

Обратите внимание, что этого можно избежать, используя функции стрелок, а не используемый синтаксис выражения функций. Это свяжет this в лексическом контексте (лексический контекст означает «где определена функция стрелки», а не «где функция вызывается»)

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      tradingFrom: "...",
      tradingTo: "...",
      result: "..."
    };
    this.retrieveValue = this.retrieveValue.bind(this);
  }

  updateResult(str) {
    var self = this;
    if (str != null) {
      self.setState({
        result: str
      });
    }
  }

  retrieveValue() {
    console.log("App: retrieveValue executed...");
    let symbol = this.state.tradingTo + this.state.tradingFrom;
    //  Make Server Request
    axios
      .get(BIN_API, {
        params: {
          symbol: symbol
        }
      })
      .then((response) => {
        this.updateResult(response.data);
        console.log("this.state.result is now " + this.state.result);
      })
      .catch((error) => {
        console.log(error);
        this.updateResult("ERROR");
      });
  }

  render() {
    return (
      <div className="App">
        <Button className="App-Button" onClick={this.retrieveValue}>
          {" "}Retrieve Value{" "}
        </Button>
        <div className="TXTAREA">
          <p className="TA-p">
            {this.state.result}
          </p>
        </div>
      </div>
    );
  }
}

Обратите внимание, что шаблон для функций bind в конструкторе компонента React используется только потому, что когда вы передаете функцию, как в обработчике onClick:

onClick={this.retrieveValue}

Вы теряете контекст this при его вызове. Чтобы решить эту проблему, используйте bind или стрелочные функции; причина, по которой используется привязка, заключается в том, что она позволяет избежать создания нового функционального объекта при каждом вызове render. Итак, с учетом сказанного, вам не нужно bind updateResult.

EDIT: обратите внимание, что этот код относится к предыдущей версии кода OP, но проблема та же самая.