Невозможно вызвать setState (или forceUpdate) для неустановленного компонента - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь получить данные с сервера после обновления компонента, но мне не удалось это сделать.Насколько я понимаю, componentWillUnmount вызывается, когда компонент собирается быть уничтоженным, но мне никогда не нужно уничтожать его, так что это бесполезно для меня.Каково было бы решение для этого?Когда мне следует установить состояние?

async componentDidUpdate(prevProps, prevState) {
  if (this.props.subject.length && prevProps.subject !== this.props.subject) {
    let result = await this.getGrades({
      student: this.props.id,
      subject: this.props.subject
    });
    this.setState({
      subject: this.props.subject,
      grades: result
    });
  }
}

async getGrades(params) {
  let response, body;

  if (params['subject'].length) {
    response = await fetch(apiRequestString.gradesBySubject(params));
    body = await response.json();
  } else {
    response = await fetch(apiRequestString.grades(params));
    body = await response.json();
  }

  if (response.status !== 200) throw Error(body.message);

  return body;
}

Полная ошибка:

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, 
but it indicates a memory leak in your application. To fix, cancel all subscriptions and
asynchronous tasks in the componentWillUnmount method.

Ответы [ 2 ]

0 голосов
/ 02 августа 2018

Принятый ответ работает и является допустимым решением проблемы вызова асинхронных функций в методах рендеринга компонента (getInitialState, componentWillMount, componentDidMount).

Но лучшей практикой будет использование помощников по управлению состоянием, таких как Redux и Flux, и глобального хранилища, это может избежать проблемы нескольких setStates.

0 голосов
/ 20 мая 2018

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

componentWillUnmount() {
    this.isCancelled = true;
}

А затем в коде, где вы ожидаете разрешения асинхронной функции, вы должны добавить проверку перед установкой состояния.:

async componentDidUpdate(prevProps, prevState) {
    if (this.props.subject.length && prevProps.subject !== this.props.subject) {
        let result = await this.getGrades({
            student: this.props.id,
            subject: this.props.subject
        });
        !this.isCancelled && this.setState({
            subject: this.props.subject,
            grades: result
        });
    }
}

Это остановит любую настройку состояния на размонтированных / размонтированных компонентах

...