Невозможно вызвать setState в обратном вызове - PullRequest
0 голосов
/ 22 февраля 2019

Я новичок в React, поэтому знаю, что, возможно, не все делаю правильно.

Я пытаюсь вызвать setStatus внутри функции обратного вызова onreadystatechange, но получаю ошибку в браузере.Код выполняет AJAX-вызов к серверу, чтобы узнать, есть ли предложенное имя пользователя в базе данных.По возвращении onreadystatechange выполняется.Там я пытаюсь установить новое сообщение об ошибке для имени пользователя, если оно уже существует.

Вот мои данные состояния:

const initialState = {
  firstname: "",
  lastname: "",
  username: "",
  password: "",
  email: "",
  firstnameError: "",
  lastnameError: "",
  usernameError: "",
  passwordError: "",
  emailError: ""
};

class SignUpForm extends Component {
  constructor() {
    super();

    this.state = initialState;

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.checkUserName = this.checkUserName.bind(this);
    this.checkEmail = this.checkEmail.bind(this);
    this.validateForm = this.validateForm.bind(this);
  }

Здесь я обновляю состояние в обработчике изменений дляполя в форме:

handleChange(e) {
    let target = e.target;
    let value = target.value;
    let name = target.name;

    if (name === "username") {
      value = value.toUpperCase();
    }

    this.setState({
      [name]: value
    });
  }

Это процедура, когда я получаю сообщение об ошибке в браузере.Строки, в которых возникает ошибка, помечены комментарием в строке ниже.

checkUserName() {
    let usernameError = "";
    let element = "";
    let checkNameResponse = "";
    let checkNameMessage = "";
    let request = "";

    let url = "";
    let userName = "";
    let requestData = "";
    let checkNameResponseJSON = "";

    request = new XMLHttpRequest();
    if (request == null) alert("Unable to create checkDBForUSerNameRequest");
    else {
      url = "/php/CheckUsername.php";
      userName = escape(document.getElementById("username").value);
      requestData = JSON.stringify({
        username: userName
      });

      request.onreadystatechange = function() {
        if (request.readyState === 4 && request.status === 200) {
          checkNameResponseJSON = JSON.parse(request.responseText);
          checkNameResponse = checkNameResponseJSON.returncode;
          checkNameMessage = checkNameResponseJSON.message;

          element = document.getElementById("SignupIcon");
          element.className = "displayIcon";

          if (checkNameResponse === 0) {
            element = document.getElementById("SignupIconFile");
            element.src = "/images/YesButton.png";
            element.alt = "Available";
            this.setState({ usernameError: "" });
          } else {
            element = document.getElementById("SignupIconFile");
            element.src = "/images/NoButton.png";
            element.alt = "Not Available";
            usernameError = checkNameMessage;
            this.setState({ usernameError: usernameError });  // BROWSER ERROR
          }
        }
      };

      request.open("POST", url, true);
      request.setRequestHeader("Content-Type", "application/json");
      request.send(requestData);
    }
  }

Это текст из ошибки браузера:

0: Object doesn't support property or method 'setState'

Любые идеи, почему это происходит и какисправить?

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Ошибка в том, что вы используете request.onreadystatechange = function() {} вместо request.onreadystatechange = () => {} или request.onreadystatechange = function() {}.bind(this)

. При использовании function() меняется область действия this.

Помнитечто function() {} и () => {} не одинаковы.

, но function(){}.bind(this) и () => {} одинаковы.

0 голосов
/ 22 февраля 2019

Вам необходимо связать функцию onreadystatechange с помощью функции .bind или arrow, так как при выполнении этой функции необходимо получить доступ к правильному значению this, относящемуся к контексту класса.

request.onreadystatechange = function() {
    // all logic here
 }.bind(this)

или

request.onreadystatechange = () => {
   //all logic here

}
...