Коли використовувати метод "компонентного оновлення" React?


108

Я написав десятки Reactфайлів, ніколи не використовую componentDidUpdateметод.

Чи є якийсь типовий приклад, коли потрібно використовувати цей метод?

Я хочу отримати приклад із реального світу, а не просту демонстрацію.

Дякую за відповідь!



Простий випадок, коли ви хочете встановити початковий стан компонента на навантаженні.
Раджеш

@Rajesh Чи можете ви пояснити це чи надати мені приклад? Дякую!
слайдшоу2

1
Я думаю, що найпоширеніший випадок використання - це коли у вас є інші бібліотеки (jQuery, D3 ...), які працюють безпосередньо над DOM разом із React. У таких сценаріях, якщо іншій бібліотеці потрібно здійснити перетворення DOM, слід використовувати компонентDidUpdate, щоб переконатися, що тінь DOM React була перенесена на реальну DOM.
Хорхе

1
На закінчення коментаря @ Jorge: Я думаю, що найпоширенішим випадком було б ЧИТАТИ з реального DOM після оновлення React. Наприклад, коли потрібно знати точні розміри елементів DOM або положення елементів DOM у вікні перегляду. Наприклад, для анімації чи переходів, на які ви хочете реагувати, керуйте. Я б точно не радив використовувати jQuery для зміни DOM після надання реакції. Реагувати + інша бібліотека змінити той самий фрагмент DOM - погана ідея.
wintvelt

Відповіді:


88

Простим прикладом може бути додаток, яке збирає вхідні дані від користувача, а потім використовує Ajax для завантаження зазначених даних у базу даних. Ось спрощений приклад (не запускайте його - можливо, є синтаксичні помилки):

export default class Task extends React.Component {
  
  constructor(props, context) {
    super(props, context);
    this.state = {
      name: "",
      age: "",
      country: ""
    };
  }

  componentDidUpdate() {
    this._commitAutoSave();
  }

  _changeName = (e) => {
    this.setState({name: e.target.value});
  }

  _changeAge = (e) => {
    this.setState({age: e.target.value});
  }

  _changeCountry = (e) => {
    this.setState({country: e.target.value});
  }

  _commitAutoSave = () => {
    Ajax.postJSON('/someAPI/json/autosave', {
      name: this.state.name,
      age: this.state.age,
      country: this.state.country
    });
  }

  render() {
    let {name, age, country} = this.state;
    return (
      <form>
        <input type="text" value={name} onChange={this._changeName} />
        <input type="text" value={age} onChange={this._changeAge} />
        <input type="text" value={country} onChange={this._changeCountry} />
      </form>
    );
  }
}

Тому щоразу, коли компонент має stateзміни, він автоматично зберігає дані. Є й інші способи їх втілення. componentDidUpdateОсобливо корисно , коли операція повинна відбутися після того, як DOM - оновлюються і черга поновлення випорожнюються. Це, ймовірно , найбільш корисним на складному rendersі stateчи DOM зміна або коли вам потрібно що - то , щоб бути абсолютно останньою річчю , яка буде виконано.

Наведений вище приклад досить простий, але, ймовірно, доводить суть. Поліпшенням може бути обмеження кількості разів, яку може виконати автоматичне збереження (наприклад, максимум кожні 10 секунд), оскільки зараз воно буде працювати на кожному натисканні клавіші.

Я також продемонстрував демонстрацію цієї скрипки , щоб продемонструвати.


Для отримання додаткової інформації зверніться до офіційних документів :

componentDidUpdate()викликається відразу після оновлення. Цей метод не вимагається для початкового візуалізації.

Використовуйте це як можливість працювати з DOM після оновлення компонента. Це також гарне місце для здійснення мережевих запитів, якщо ви порівнюєте поточний реквізит з попередніми реквізитами (наприклад, мережевий запит може не знадобитися, якщо реквізит не змінився).


Я думаю this.setState({...}, callback), callbackрівний _commitAutoSave, що ти думаєш? Отже, я думаю, що у цьому випадку можна використовувати componentDidUpdateметод, але не обов'язково, чи я прав? fiddle
слайдшоу2

1
Так, ви можете використовувати зворотний виклик, однак проблема стає складнішою, коли / якщо є декілька setStates, які виконуються послідовно.
Кріс

Дякую за вашу відповідь. Отже, одним із випадків використання componentDidUpdateє вирішення декількох setStates! Будь-які інші ідеї?
слайдшоу2

@novaline Я бачу, що вони використовують його в реактивно -звуковому компоненті github.com/leoasis/react-sound/blob/master/src/index.js .. Я не зовсім впевнений, чому вони використовують його, але я подумав, що я поділююсь посиланням для вас, щоб подивитися.
Сара

3
Це хороший приклад, але в ньому відсутня ключова рекомендація від документів React. "Це також гарне місце для здійснення мережевих запитів, якщо ви порівнюєте поточний реквізит з попередніми реквізитами (наприклад, мережевий запит може не знадобитися, якщо реквізит не змінився)." reactjs.org/docs/react-component.html#componentdidupdate Аналогічно, виклик слід перетворювати в умовну логіку під час виклику setStateв CDU.
thetherSide

5

Іноді ви можете додати значення стану від реквізиту в конструкторі або компонентіDidMount, можливо, вам потрібно буде викликати setState, коли реквізит змінився, але компонент уже встановлений, тому компонентDidMount не виконається і конструктор не виконає; у цьому конкретному випадку ви можете використовувати компонентDidUpdate з моменту зміни реквізиту, ви можете викликати setState в компонентDidUpdate за допомогою нових реквізитів.


2

Я використовував componentDidUpdate()у високій діаграмі.

Ось простий приклад цього компонента.

import React, { PropTypes, Component } from 'react';
window.Highcharts = require('highcharts');

export default class Chartline extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      chart: ''
    };
  }

  public componentDidUpdate() {
    // console.log(this.props.candidate, 'this.props.candidate')
    if (this.props.category) {
      const category = this.props.category ? this.props.category : {};
      console.log('category', category);
      window.Highcharts.chart('jobcontainer_' + category._id, {
        title: {
          text: ''
        },
        plotOptions: {
          series: {
            cursor: 'pointer'
          }
        },
        chart: {
          defaultSeriesType: 'spline'
        },
        xAxis: {
          // categories: candidate.dateArr,
          categories: ['Day1', 'Day2', 'Day3', 'Day4', 'Day5', 'Day6', 'Day7'],
          showEmpty: true
        },
        labels: {
          style: {
            color: 'white',
            fontSize: '25px',
            fontFamily: 'SF UI Text'
          }
        },
        series: [
          {
            name: 'Low',
            color: '#9B260A',
            data: category.lowcount
          },
          {
            name: 'High',
            color: '#0E5AAB',
            data: category.highcount
          },
          {
            name: 'Average',
            color: '#12B499',
            data: category.averagecount
          }
        ]
      });
    }
  }
  public render() {
    const category = this.props.category ? this.props.category : {};
    console.log('render category', category);
    return <div id={'jobcontainer_' + category._id} style={{ maxWidth: '400px', height: '180px' }} />;
  }
}

2
componentDidUpdate(prevProps){ 

    if (this.state.authToken==null&&prevProps.authToken==null) {
      AccountKit.getCurrentAccessToken()
      .then(token => {
        if (token) {
          AccountKit.getCurrentAccount().then(account => {
            this.setState({
              authToken: token,
              loggedAccount: account
            });
          });
        } else {
          console.log("No user account logged");
        }
      })
      .catch(e => console.log("Failed to get current access token", e));

    }
}

1

Цей метод життєвого циклу використовується, як тільки відбувається оновлення. Найпоширенішим випадком використання методу компонентDidUpdate () є оновлення DOM у відповідь на зміни або стан.

Ви можете зателефонувати setState () у цьому життєвому циклі, але майте на увазі, що вам потрібно буде перетворити його в умову, щоб перевірити стан або підтримати зміни від попереднього стану. Неправильне використання setState () може призвести до нескінченного циклу. Погляньте на приклад нижче, який показує типовий приклад використання цього методу життєвого циклу.

componentDidUpdate(prevProps) {
 //Typical usage, don't forget to compare the props
 if (this.props.userName !== prevProps.userName) {
   this.fetchData(this.props.userName);
 }
}

Зауважте у наведеному вище прикладі, що ми порівнюємо поточний реквізит із попереднім реквізитом. Це потрібно перевірити, чи відбулася зміна реквізиту від того, що вона є. У цьому випадку не потрібно робити виклик API, якщо реквізит не змінився.

Для отримання додаткової інформації зверніться до офіційних документів:


Що робити у випадку this.fetchData is not a function?
tomrlh

tomrlh це функція виклику
Kashif

0

Коли щось у державі змінилося, і вам потрібно викликати побічний ефект (наприклад, запит на api - отримати, поставити, опублікувати, видалити). Тож вам потрібно дзвонити, componentDidUpdate()тому що componentDidMount()вже дзвонили.

Після виклику побічного ефекту в компонентDidUpdate (), ви можете встановити стан нового значення на основі даних відповідей у then((response) => this.setState({newValue: "here"})). Переконайтеся, що вам потрібно перевірити prevPropsабо prevStateуникнути нескінченного циклу, оскільки, встановивши стан на нове значення, компонентDidUpdate () знову зателефонує.

Є два місця для виклику побічного ефекту для найкращої практики - компонентDidMount () та компонентDidUpdate ()

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.