Quando usar o método React “componentDidUpdate”?

108

Escrevi dezenas de Reactarquivos, nunca use o componentDidUpdatemétodo.

Existe algum exemplo típico de quando é necessário usar esse método?

Eu quero algum exemplo do mundo real, não uma simples demonstração.

Obrigado pela resposta!

slideshowp2
fonte
Um caso simples quando você deseja definir o estado inicial do componente durante o carregamento.
Rajesh
@Rajesh Você pode me explicar ou me dar um exemplo? Obrigado!
apresentação de slides 2 de
1
Acho que o caso de uso mais comum é quando você tem outras bibliotecas (jQuery, D3 ...) que funcionam diretamente no DOM, juntamente com o React. Em tais cenários, se a outra biblioteca precisar realizar transformações DOM, você deve usar o componentDidUpdate para garantir que o DOM sombra do React foi liberado para o DOM real.
Jorge
1
Para desenvolver o comentário de @Jorge: Acho que o caso mais comum seria READ do DOM real depois que o React for atualizado. Por exemplo, quando você deseja saber as dimensões exatas dos elementos DOM ou a posição dos elementos DOM na janela de visualização. Por exemplo, para animações ou transições que você deseja gerenciar. Eu definitivamente desaconselho o uso de jQuery para alterar o DOM após a renderização de react. Ter react + outra biblioteca mudando o mesmo pedaço de DOM é uma má ideia.
wintvelt

Respostas:

88

Um exemplo simples seria um aplicativo que coleta dados de entrada do usuário e, em seguida, usa Ajax para carregar esses dados em um banco de dados. Aqui está um exemplo simplificado (não executei - pode haver erros de sintaxe):

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>
    );
  }
}

Portanto, sempre que o componente tiver uma statealteração, ele salvará os dados automaticamente. Existem outras maneiras de implementá-lo. O componentDidUpdateé particularmente útil quando uma operação precisa acontecer depois que o DOM é atualizado e a fila de atualização é esvaziada. É provavelmente mais útil em alterações complexas renderse / stateou DOM ou quando você precisa que algo seja absolutamente a última coisa a ser executada.

O exemplo acima é bastante simples, mas provavelmente prova o ponto. Uma melhoria poderia ser limitar a quantidade de vezes que o salvamento automático pode ser executado (por exemplo, no máximo a cada 10 segundos) porque agora ele será executado a cada pressionamento de tecla.

Eu fiz uma demonstração sobre este violino também para demonstrar.


Para obter mais informações, consulte os documentos oficiais :

componentDidUpdate()é chamado imediatamente após a atualização ocorrer. Este método não é chamado para a renderização inicial.

Use isso como uma oportunidade para operar no DOM quando o componente for atualizado. Este também é um bom lugar para fazer solicitações de rede, desde que você compare os props atuais com os anteriores (por exemplo, uma solicitação de rede pode não ser necessária se os props não mudaram).

Chris
fonte
Eu acho this.setState({...}, callback), callbackigual _commitAutoSave, o que você acha? Então, eu acho que esse caso pode usar componentDidUpdatemétodo, mas não deve, estou certo? fiddle
slideshowp2
1
Sim, você poderia usar um retorno de chamada, no entanto, o problema fica mais complicado quando / se houver vários setStates executados em sucessão.
Chris
Obrigado pela sua resposta. Portanto, um caso a ser usado componentDidUpdateé resolver vários setStates! Alguma outra ideia?
slideshowp2
@novaline Vejo que eles o usam no componente de som reactivo github.com/leoasis/react-sound/blob/master/src/index.js .. Não sei exatamente por que estão usando, mas pensei que compartilharia o link para você dar uma olhada.
Sarah
3
Este é um bom exemplo, mas está faltando uma recomendação importante dos documentos do React. "Este também é um bom lugar para fazer solicitações de rede, desde que você compare os props atuais com os anteriores (por exemplo, uma solicitação de rede pode não ser necessária se os props não mudaram)." reactjs.org/docs/react-component.html#componentdidupdate Da mesma forma, deve-se envolver a chamada em lógica condicional sempre que chamar setStateem CDU.
theUtherSide
5

Às vezes, você pode adicionar um valor de estado a partir de props no construtor ou componentDidMount, você pode precisar chamar setState quando os props mudaram, mas o componente já foi montado, então componentDidMount não será executado e nem o construtor; neste caso específico, você pode usar componentDidUpdate, já que os adereços foram alterados, você pode chamar setState em componentDidUpdate com novos adereços.

Hasan Ahmed
fonte
2

Eu usei componentDidUpdate()em highchart.

Aqui está um exemplo simples deste componente.

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' }} />;
  }
}
Link Asad
fonte
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));

    }
}
James Siva
fonte
1

Este método de ciclo de vida é chamado assim que ocorre a atualização. O caso de uso mais comum para o método componentDidUpdate () é atualizar o DOM em resposta a alterações de propriedade ou estado.

Você pode chamar setState () neste ciclo de vida, mas lembre-se de que você precisará envolvê-lo em uma condição para verificar se há mudanças de estado ou prop em relação ao estado anterior. O uso incorreto de setState () pode levar a um loop infinito. Dê uma olhada no exemplo abaixo que mostra um exemplo típico de uso deste método de ciclo de vida.

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

Observe no exemplo acima que estamos comparando os acessórios atuais com os anteriores. Isso é para verificar se houve uma mudança nos adereços em relação ao que é atualmente. Nesse caso, não haverá necessidade de fazer a chamada API se os adereços não forem alterados.

Para obter mais informações, consulte os documentos oficiais:

Kashif
fonte
O que fazer em caso de this.fetchData is not a function?
tomrlh
amanha é uma chamada de função
Kashif
0

Quando algo no estado mudou e você precisa chamar um efeito colateral (como uma solicitação para api - get, put, post, delete). Então você precisa ligar componentDidUpdate()porque componentDidMount()já está ligado.

Depois de chamar o efeito colateral em componentDidUpdate (), você pode definir o estado para um novo valor com base nos dados de resposta no then((response) => this.setState({newValue: "here"})). Certifique-se de que você precisa verificar prevPropsou prevStateevitar o loop infinito, pois ao definir o estado para um novo valor, o componentDidUpdate () irá chamar novamente.

Existem 2 lugares para chamar um efeito colateral para as melhores práticas - componentDidMount () e componentDidUpdate ()

K.tin
fonte