Che cos'è il simbolo "@" (sul simbolo) nel decoratore Redux @connect?


226

Sto imparando Redux con React e mi sono imbattuto in questo codice. Non sono sicuro che sia specifico di Redux o meno, ma ho visto il seguente frammento di codice in uno degli esempi.

@connect((state) => {
  return {
    key: state.a.b
  };
})

Mentre la funzionalità di connectè piuttosto semplice, ma non capisco il @prima connect. Non è nemmeno un operatore JavaScript se non sbaglio.

Qualcuno può spiegare per favore di cosa si tratta e perché viene utilizzato?

Aggiornare:

In realtà è una parte della react-reduxquale viene utilizzata per connettere un componente React a un negozio Redux.


6
Non ho familiarità con Redux, ma sembra un decoratore. medium.com/google-developers/…
Lee

4
Adoro come in questo nuovo mondo JavaScript stai fissando il codice metà del tempo e pensando "che parte della sintassi del linguaggio è questa?"
MK.

4
Lol, sono profondamente coinvolto nella redux e nelle cose adesso. Ma allora non sapevo che la sintassi del decoratore non avesse nulla a che fare con il redux. È solo JavaScript. Sono contento di vedere questa domanda che sta aiutando molte persone come me. :)
Salman,

1
Apparentemente il team di redux scoraggia l'uso di connect come decoratore al momento github.com/happypoulp/redux-tutorial/issues/87
Syed Jafri,

Risposte:


376

Il @simbolo è in realtà un'espressione JavaScript attualmente proposta per indicare i decoratori :

I decoratori consentono di annotare e modificare classi e proprietà in fase di progettazione.

Ecco un esempio di configurazione di Redux senza e con un decoratore:

Senza un decoratore

import React from 'react';
import * as actionCreators from './actionCreators';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

function mapStateToProps(state) {
  return { todos: state.todos };
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) };
}

class MyApp extends React.Component {
  // ...define your main app here
}

export default connect(mapStateToProps, mapDispatchToProps)(MyApp);

Usando un decoratore

import React from 'react';
import * as actionCreators from './actionCreators';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

function mapStateToProps(state) {
  return { todos: state.todos };
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) };
}

@connect(mapStateToProps, mapDispatchToProps)
export default class MyApp extends React.Component {
  // ...define your main app here
}

Entrambi gli esempi sopra sono equivalenti, è solo una questione di preferenza. Inoltre, la sintassi del decoratore non è ancora integrata in nessun runtime Javascript, ed è ancora sperimentale e soggetta a modifiche. Se vuoi usarlo, è disponibile usando Babel .


46
è fantastico
svnm

2
Si può anche essere più concisi con la sintassi ES6. @connect (state => {return {todos: state.todos};}, dispatch => {return {actions: bindActionCreators (actionCreators, dispatch)};})
LessQuesar

11
Se vuoi davvero essere conciso puoi usare rendimenti impliciti in ES6. Dipende da quanto esplicito vuoi essere. @connect(state => ({todos: state.todos}), dispatch => ({actions: bindActionCreators(actionCreators, dispatch)}))
Tanner Semerad,

3
Come esportereste il componente non collegato per i test unitari?
tim

L'uso di decorator per il redux con la reattanza di navigazione può essere problematico, l'attuale best practice consiste nell'utilizzare la funzione e non il decoratore: github.com/react-community/react-navigation/issues/1180
straya,

50

Molto importante!

Questi oggetti di scena sono chiamati oggetti di stato e sono diversi dai normali oggetti di scena, qualsiasi modifica agli oggetti di stato del componente attiverà ripetutamente il metodo di rendering dei componenti anche se non li usi, quindi per motivi di prestazioni prova a legare solo al tuo componente gli oggetti di scena dello stato necessari all'interno del componente e se si utilizza un oggetto secondario si vincolano solo questi oggetti di scena.

esempio: diciamo all'interno del tuo componente hai solo bisogno di due oggetti di scena:

  1. l'ultimo messaggio
  2. il nome utente

non farlo

@connect(state => ({ 
   user: state.user,
   messages: state.messages
}))

Fai questo

@connect(state => ({ 
   user_name: state.user.name,
   last_message: state.messages[state.messages.length-1]
}))

9
oppure usa selettori come riseleziona o modifica veloce
Julius Koronci,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.