Was ist das '@' (am Symbol) im Redux @ connect-Dekorator?

226

Ich lerne Redux mit React und bin auf diesen Code gestoßen. Ich bin nicht sicher, ob es Redux- spezifisch ist oder nicht, aber ich habe das folgende Code-Snippet in einem der Beispiele gesehen.

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

Die Funktionalität von connectist zwar ziemlich einfach, aber ich verstehe das @vorher nicht connect. Es ist nicht einmal ein JavaScript-Operator, wenn ich mich nicht irre.

Kann jemand bitte erklären, was das ist und warum es verwendet wird?

Aktualisieren:

Tatsächlich wird ein Teil react-reduxdavon verwendet, um eine React-Komponente mit einem Redux-Speicher zu verbinden.

Salman
quelle
6
Ich kenne Redux nicht, aber es sieht aus wie ein Dekorateur. medium.com/google-developers/…
Lee
4
Ich finde es toll, wie Sie in dieser neuen JavaScript-Welt die Hälfte der Zeit auf den Code starren und denken: "Welcher Teil der Sprachsyntax ist das?"
MK.
4
Lol, ich bin jetzt sehr tief in Redux und so. Aber damals wusste ich nicht, dass die Dekorationssyntax nichts mit Redux zu tun hat. Es ist nur JavaScript. Ich bin froh zu sehen, dass diese Frage vielen Menschen wie mir hilft. :)
Salman
1
Anscheinend rät das Redux-Team derzeit von der Verwendung von Connect als Dekorateur ab. Github.com/happypoulp/redux-tutorial/issues/87
Syed Jafri

Antworten:

376

Das @Symbol ist in der Tat ein JavaScript-Ausdruck, der derzeit vorgeschlagen wird, um Dekorateure zu kennzeichnen :

Dekorateure ermöglichen das Kommentieren und Ändern von Klassen und Eigenschaften zur Entwurfszeit.

Hier ist ein Beispiel für die Einrichtung von Redux ohne und mit einem Dekorateur:

Ohne Dekorateur

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

Mit einem Dekorateur

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
}

Beide obigen Beispiele sind gleichwertig, es ist nur eine Frage der Präferenz. Außerdem ist die Decorator-Syntax noch nicht in Javascript-Laufzeiten integriert und noch experimentell und kann sich ändern. Wenn Sie es verwenden möchten, ist es mit Babel verfügbar .

Tanner Semerad
quelle
46
das ist fantastisch
svnm
2
Mit der ES6-Syntax kann man noch knapper sein. @connect (state => {return {todos: state.todos};}, dispatch => {return {action: bindActionCreators (actionCreators, dispatch)};})
LessQuesar
11
Wenn Sie wirklich knapp sein möchten, können Sie implizite Rückgaben in ES6 verwenden. Es hängt davon ab, wie explizit Sie sein möchten. @connect(state => ({todos: state.todos}), dispatch => ({actions: bindActionCreators(actionCreators, dispatch)}))
Tanner Semerad
3
Wie würden Sie die nicht verbundene Komponente für Unit-Tests exportieren?
Tim
Die Verwendung von Decorator für Redux mit React-Navigation kann problematisch sein.
Derzeit wird empfohlen,
50

Sehr wichtig!

Diese Requisiten werden als Status-Requisiten bezeichnet und unterscheiden sich von normalen Requisiten. Jede Änderung an Ihren Komponenten-Status-Requisiten löst die Komponenten-Rendermethode immer wieder aus, auch wenn Sie diese Requisiten nicht verwenden. Versuchen Sie daher aus Leistungsgründen, nur an Ihre Komponente zu binden Die Status-Requisiten, die Sie in Ihrer Komponente benötigen, und wenn Sie Unter-Requisiten verwenden, binden diese Requisiten nur.

Beispiel: Nehmen wir an, Sie benötigen in Ihrer Komponente nur zwei Requisiten:

  1. die letzte Nachricht
  2. der Nutzername

Tu das nicht

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

mach das

@connect(state => ({ 
   user_name: state.user.name,
   last_message: state.messages[state.messages.length-1]
}))
Fareed Alnamrouti
quelle
9
oder verwenden Sie Selektoren wie reselect oder fastmemoize
Julius Koronci