How to fix "cannot update during an existing state transition (such as within `render`)" problem?

Viewed 38

I get this problem even though my code doesn't update the state directly.

Here's my code:

export class Login extends React.Component {
  static contextType = getContext();

  _usernameValue = "";
  _passwordValue = "";
  // adding value to notification variable activates notification
  state = { mode: "signin", notification: "" };

  constructor(props) {
    super(props);
    this.showNotificationDeb = debounceOnce(this.showNotification, 200);
    this.closeNotificationDeb = debounceOnce(this.closeNotification, 200);
  }

  signinClicked = () => {
    this.context.dispatch({
      type: "LOGIN",
      payload: {
        username: this._usernameValue,
        password: this._passwordValue,
        callback: this.incorrectCredentials,
      },
    });
  };

  forgotPasswordClicked = () => {
    this.setState({ mode: "password" });
  };

  sendPasswordRequest = () => {
    this.context.dispatch({
      type: "FORGOT_PASSWORD",
      payload: {
        username: this._usernameValue,
        password: this._passwordValue,
        callback: this.passwordRequestSent,
      },
    });
  };

  incorrectCredentials = (errorMessage) => {
    this.showNotificationDeb(errorMessage);
  };

  passwordRequestSent = (message) => {
    this.showNotificationDeb(message);
  };

  restoreSigninWindow = () => {
    this.setState({ mode: "signin" });
  };

  showNotification = (message) => {
    console.log("aa");
    this.setState({ notification: message });
  };

  closeNotification = () => {
    if (this.state.notification) this.setState({ notification: "" });
  };

  render() {
    return (
      <div className={styles.container}>
        <div className={styles.loginContainer}>
          <Icon
            rotate={90}
            path={mdiCog}
            size={2}
            color="black"
            className={styles.loginIcon}
          />
          <p className={styles.loginTitle}>Sign in to RAS</p>
          <div
            className={`${styles.notificationContainer} ${
              this.state.notification ? "" : styles.hideNotification
            }`}
          >
            <p className={styles.notificationMessage}>
              {this.state.notification}
            </p>
            <p
              className={styles.notificationCloseButton}
              onClick={() => this.closeNotification()}
            >
              x
            </p>
          </div>
          <div className={styles.loginWindow}>
            {this.state.mode === "signin" ? (
              <React.Fragment>
                <label className={styles.inputLabel}>Username</label>
                <input
                  id="usernameInput"
                  className={styles.input}
                  onChange={(event) => {
                    this._usernameValue = event.target.value;
                  }}
                ></input>
                <div className={styles.passwordLabelContainer}>
                  <label className={styles.inputLabel}>Password</label>
                  <p
                    className={styles.forgotPasswordLabel}
                    onClick={() => this.forgotPasswordClicked()}
                  >
                    Forgot password?
                  </p>
                </div>
                <input
                  id="passwordInput"
                  type="password"
                  className={styles.input}
                  onChange={(event) => {
                    this._passwordValue = event.target.value;
                  }}
                ></input>
                <Button
                  variant="contained"
                  className={styles.button}
                  onClick={() => this.signinClicked()}
                >
                  Sign in
                </Button>
              </React.Fragment>
            ) : (
              <React.Fragment>
                <div className={styles.backButtonContainer}>
                  <div onClick={() => this.restoreSigninWindow()}>
                    <Icon
                      path={mdiKeyboardBackspace}
                      size={0.85}
                      color="black"
                      className={styles.backIcon}
                    />
                    <p>Back</p>
                  </div>
                </div>
                <label className={`${styles.inputLabel}`}>
                  Enter your email address. Password reset link will be send to
                  your email address.
                </label>
                <input
                  id="usernameInput"
                  className={styles.input}
                  placeholder="Enter your email address"
                ></input>

                <Button
                  variant="contained"
                  className={styles.button}
                  onClick={() => this.sendPasswordRequest()}
                >
                  Send
                </Button>
              </React.Fragment>
            )}
          </div>
        </div>
      </div>
    );
  }
}

As you see, I don't change the state directly. I do it always by calling the functions above. However, according to the React I am changing the state from inside render() function.

I do use lambda functions but I still see the problem.

0 Answers
Related