@miniven

Почему возникает ошибка «Can't call setState (or forceUpdate) on an unmounted component» в React?

Почему после удачной авторизации, в момент редиректа выводится ошибка: take.ms/IiSyE
При этом дальше все работает без проблем

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';

// Styles //

import './LoginForm.css';

// Components //

import WithLoading from '~/hoc/WithLoading/WithLoading';
import ErrorBox from '~/components/ErrorBox/ErrorBox';

// Actions //

import { logIn } from '../../actions/auth';

const LoadingButton = WithLoading(() => <button className='form__submit button' type='submit'>Войти</button>);

class LoginForm extends Component {
  state = {
    data: {
      email: 'max@test.com',
      password: '12345'
    },
    redirectToPrevRoute: false
  }

  onInputChange = ({ target }) => {
    this.setState({
      data: {
        ...this.state.data,
        [target.name]: target.value
      }
    });
  }

  onSubmit = (event) => {
    event.preventDefault();

    if (!this.props.auth.fetching) {
      this.tryLogIn();
    }
  }

  tryLogIn = () => {
    const { logIn } = this.props;

    logIn(this.state.data)
      .then((data) => {
        if (data.status === 'ok') {
          this.setState({ redirectToPrevRoute: true });

          return;
        }

        this.setState({
          data: {
            ...this.state.data,
            password: '',
          },
        });
      });
  }

  render() {
    if (this.state.redirectToPrevRoute) return <Redirect to='/profile' />

    const { email, password } = this.state.data;
    const { error, fetching } = this.props.auth;

    return (
      <form className={`${this.props.className ? this.props.className : ''} form`} onSubmit={this.onSubmit}>
        { error && <ErrorBox errorCode={error} /> }
        <input
          className='form__input'
          type='email'
          name='email'
          onChange={this.onInputChange}
          value={email}
          autoComplete="off"
          placeholder='Email'
        />
        <input
          className='form__input'
          type='password'
          name='password'
          onChange={this.onInputChange}
          value={password}
          placeholder='Пароль'
        />
        <div className="form__footer">
          <LoadingButton isLoading={fetching} />
        </div>
      </form>
    );
  }
};

LoginForm.propTypes = {
  className: PropTypes.string,
  logIn: PropTypes.func.isRequired,
  auth: PropTypes.shape({
    error: PropTypes.string,
    fetching: PropTypes.bool.isRequired,
  }).isRequired,
};

const mapStateToProps = state => ({
  auth: state.auth,
});

export default connect(mapStateToProps, { logIn })(LoginForm);
  • Вопрос задан
  • 1011 просмотров
Решения вопроса 1
@miniven Автор вопроса
Нашел, ошибку: у меня в Redux сторе меняется флаг авторизации и, т.к. текущая страница приватная, то компонент "размонтируется", а в нем еще должен then с асинхронным setState сработать после авторизации. В итоге убрал ненужную проверку на this.state.redirectToPrevRoute, т.к. роут и так приватный и редирект произойдет в любом случае, когда изменится флаг в сторе
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Привет, Бэн! Текст ошибки говорит о том, что вызываешь setState в компоненте, который уже "размонтирован" (то есть, которого уже нет на странице). Причина ошибки - лишнее обновление. Можно решить (код не смотрел внимательно) либо добавлением флага в componentWillUnmount и потом этот флаг проверять там, где обновления происходит, либо попробовать избавиться от причины этого обновления.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы