Reagire componente stateless funzionale, PureComponent, Component; quali sono le differenze e quando dovremmo usare cosa?

È venuto a sapere che da React v15.3.0 , abbiamo una nuova class base chiamata PureComponent da estendere con PureRenderMixin integrato. Quello che capisco è che, sotto la cappa, si impiega un confronto superficiale di oggetti di scena all’interno di shouldComponentUpdate .

Ora abbiamo 3 modi per definire un componente React:

  1. Componente stateless funzionale che non estende alcuna class
  2. Un componente che estende la class PureComponent
  3. Un componente normale che estende la class Component

Qualche tempo fa eravamo soliti chiamare componenti stateless come Pure Components, o anche Componenti stupidi. Sembra che l’intera definizione della parola “puro” sia cambiata in React.

Anche se capisco le differenze di base tra questi tre, non sono ancora sicuro quando scegliere cosa . Inoltre quali sono gli impatti sulle prestazioni e i compromessi di ciascuno?


Aggiornamento :

Queste sono le domande che mi aspetto di chiarire:

  • Dovrei scegliere di definire i miei componenti semplici come funzionali (per ragioni di semplicità) o di estendere la class PureComponent (per motivi di prestazioni)?
  • Il potenziamento delle prestazioni mi procura un vero e proprio trade-off per la semplicità che ho perso?
  • Avrei mai PureComponent bisogno di estendere la normale class Component quando posso sempre utilizzare PureComponent per prestazioni migliori?

Come decidi, come scegli tra questi tre in base allo scopo / dimensione / props / comportamento dei nostri componenti?

L’estensione da React.PureComponent o da React.Component con un metodo shouldComponentUpdate personalizzato ha implicazioni sulle prestazioni. L’utilizzo di componenti funzionali stateless è una scelta “architettonica” e non ha ancora alcun vantaggio sulle prestazioni (al momento).

  • Per componenti semplici e di presentazione che devono essere facilmente riutilizzati, preferisci componenti funzionali senza stato. In questo modo sei sicuro che siano disaccoppiati dall’effettiva logica dell’app, che siano morti, facili da testare e che non abbiano effetti collaterali imprevisti. L’eccezione è se per qualche motivo ne hai molti o se hai davvero bisogno di ottimizzare il loro metodo di rendering (dato che non puoi definire shouldComponentUpdate per un componente funzionale stateless).

  • Estendi PureComponent se sai che il tuo output dipende da semplici oggetti di scena / stato (“semplice” che significa strutture di dati non annidate, dato che PureComponent esegue un confronto poco profondo) E hai bisogno / puoi ottenere alcuni miglioramenti delle prestazioni.

  • Estendi Component e implementa il tuo shouldComponentUpdate se hai bisogno di alcuni miglioramenti delle prestazioni eseguendo una logica di confronto personalizzata tra oggetti di scena e stato prossimi / attuali. Ad esempio, puoi eseguire rapidamente un confronto approfondito usando lodash # isEqual:

     class MyComponent extends Component { shouldComponentUpdate (nextProps, nextState) { return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState); } } 

Inoltre, l’implementazione del proprio shouldComponentUpdate o l’estensione da PureComponent sono ottimizzazioni e, come al solito, si dovrebbe iniziare a esaminarlo solo se si PureComponent problemi di prestazioni ( evitare ottimizzazioni premature ). Come regola generale, cerco sempre di eseguire queste ottimizzazioni dopo che l’applicazione si trova in uno stato funzionante, con la maggior parte delle funzionalità già implementate. È molto più facile concentrarsi sui problemi di prestazioni quando si intromettono.

Più dettagli

Componenti stateless funzionali:

Questi sono definiti solo usando una funzione. Poiché non esiste uno stato interno per un componente stateless, l’output (ciò che viene reso) dipende solo dai puntelli dati come input per questa funzione.

Professionisti:

  • Il modo più semplice ansible di definire un componente in React. Se non è necessario gestire alcun stato, perché preoccuparsi delle classi e dell’ereditarietà? Una delle principali differenze tra una funzione e una class è che con la funzione si è certi che l’output dipende solo dall’input (non da alcuna cronologia delle esecuzioni precedenti).

  • Idealmente nella tua app dovresti mirare ad avere il maggior numero ansible di componenti stateless, perché questo normalmente significa che hai spostato la tua logica al di fuori del livello di vista e spostato in qualcosa di simile a redux, il che significa che puoi testare la tua vera logica senza dover eseguire alcun rendering (molto più facile da testare, più riutilizzabile, ecc.).

Contro:

  • Nessun metodo del ciclo di vita. Non hai un modo per definire componentDidMount e altri amici. Normalmente lo fai all’interno di un componente genitore più in alto nella gerarchia in modo da poter trasformare tutti i bambini in apolidi.

  • Non è ansible controllare manualmente quando è necessario eseguire nuovamente il rendering, poiché non è ansible definire shouldComponentUpdate . Un re-rendering avviene ogni volta che il componente riceve nuovi oggetti di scena (non c’è modo di confrontare superficialmente, ecc.). In futuro, React potrebbe ottimizzare automaticamente i componenti senza stato, per ora ci sono alcune librerie che puoi usare. Poiché i componenti stateless sono solo funzioni, fondamentalmente è il classico problema della “funzione memoization”.

  • I riferimenti non sono supportati: https://github.com/facebook/react/issues/4936

Un componente che estende la class PureComponent VS Un componente normale che estende la class Component:

React utilizzato per avere un PureRenderMixin è ansible albind a una class definita utilizzando la syntax React.createClass . Il mixin definiva semplicemente un shouldComponentUpdate esegue un confronto superficiale tra i prossimi oggetti di scena e lo stato successivo per verificare se qualcosa è cambiato. Se non cambia nulla, non è necessario eseguire un nuovo rendering.

Se si desidera utilizzare la syntax ES6, non è ansible utilizzare mixins. Quindi, per praticità, React ha introdotto una class PureComponent è ansible ereditare anziché utilizzare Component . PureComponent implementa shouldComponentUpdate nello stesso modo di PureRendererMixin . È soprattutto una comodità, quindi non è necessario implementarlo da soli, in quanto un confronto superficiale tra lo stato corrente / successivo e gli oggetti di scena è probabilmente lo scenario più comune che può darti delle vincite veloci.

Esempio:

 class UserAvatar extends Component { render() { return 
{{ this.props.username }}
} }

Come puoi vedere l’output dipende da props.imageUrl e props.username . Se in un componente padre rendi con gli stessi oggetti di scena, React chiamerebbe render ogni volta, anche se l’output sarebbe esattamente lo stesso. Ricorda però che React implementa dom diffing, quindi il DOM non verrebbe aggiornato. Tuttavia, eseguire la doming può essere costoso, quindi in questo scenario sarebbe uno spreco.

Se invece il componente UserAvatar estende PureComponent , viene eseguito un confronto poco profondo. E poiché gli oggetti di scena e nextProps sono gli stessi, il render non verrà chiamato affatto.

Note sulla definizione di “puro” in React:

In generale, una “funzione pura” è una funzione che valuta sempre lo stesso risultato dato lo stesso input. L’output (per React, questo è ciò che viene restituito dal metodo render ) non dipende da alcuna storia / stato e non ha effetti collaterali (operazioni che cambiano il “mondo” al di fuori della funzione).

In React, i componenti stateless non sono necessariamente componenti puri secondo la definizione precedente se si chiama “stateless” un componente che non chiama mai this.setState e che non usa this.state .

In effetti, in un PureComponent , è comunque ansible eseguire effetti collaterali durante i metodi del ciclo di vita. Ad esempio, è ansible inviare una richiesta Ajax all’interno di componentDidMount oppure eseguire alcuni calcoli DOM per regolare dynamicmente l’altezza di un div all’interno del render .

La definizione “Componenti stupidi” ha un significato più “pratico” (almeno a mio avviso): una componente stupida “viene detta” cosa fare da un componente genitore tramite oggetti di scena, e non sa come fare cose ma usa oggetti di scena callbacks invece.

Esempio di un componente “intelligente” AvatarComponent :

 class AvatarComponent extends Component { expandAvatar () { this.setState({ loading: true }); sendAjaxRequest(...).then(() => { this.setState({ loading: false }); }); } render () { 
} }

Esempio di un componente AvatarComponent “stupido”:

 class AvatarComponent extends Component { render () { 
{this.props.loading &&
}
} }

Alla fine direi che “stupido”, “apolide” e “puro” sono concetti abbastanza diversi che a volte possono sovrapporsi, ma non necessariamente, a seconda del caso d’uso.

Non sono un genio a reactjs, ma dalla mia comprensione possiamo usare ogni componente nelle seguenti situazioni

  1. Componente senza stato: questi sono i componenti che non hanno un ciclo di vita, quindi quei componenti dovrebbero essere usati per rendere l’elemento di ripetizione del componente padre come il rendering della lista di testo che mostra solo le informazioni e non ha azioni da eseguire.

  2. Componente puro: questi sono gli articoli che hanno un ciclo di vita e restituiranno sempre lo stesso risultato quando viene fornito un insieme specifico di oggetti di scena. Questi componenti possono essere utilizzati durante la visualizzazione di un elenco di risultati o di dati specifici di un object che non hanno elementi figlio complessi e utilizzati per eseguire operazioni che hanno un impatto solo su se stesso. tale elenco di visualizzazione di tabs utente o di tabs prodotti (informazioni di base sul prodotto) e l’azione che l’utente può eseguire è solo un clic per visualizzare la pagina di dettaglio o aggiungere al carrello.

  3. Componenti normali o componenti complessi – Ho usato componenti complessi a termine perché quelli sono di solito i componenti a livello di pagina e sono costituiti da molti componenti secondari e dal momento che ciascuno di essi può comportarsi nel suo modo unico in modo da non essere sicuro al 100% che sarà restituisce lo stesso risultato in uno stato dato. Come ho detto di solito questi dovrebbero essere usati come componenti del contenitore