@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);
  • Вопрос задан
  • 1015 просмотров
Решения вопроса 1
@miniven Автор вопроса
Нашел, ошибку: у меня в Redux сторе меняется флаг авторизации и, т.к. текущая страница приватная, то компонент "размонтируется", а в нем еще должен then с асинхронным setState сработать после авторизации. В итоге убрал ненужную проверку на this.state.redirectToPrevRoute, т.к. роут и так приватный и редирект произойдет в любом случае, когда изменится флаг в сторе
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Привет, Бэн! Текст ошибки говорит о том, что вызываешь setState в компоненте, который уже "размонтирован" (то есть, которого уже нет на странице). Причина ошибки - лишнее обновление. Можно решить (код не смотрел внимательно) либо добавлением флага в componentWillUnmount и потом этот флаг проверять там, где обновления происходит, либо попробовать избавиться от причины этого обновления.
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы