Що означає "@" (у символі) в декораторі Redux @connect?


226

Я вивчаю Redux з React і натрапив на цей код. Я не впевнений, характерний він для Redux чи ні, але я бачив наступний фрагмент коду в одному з прикладів.

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

Хоча функціональність connectдосить проста, але я не розумію , @перш ніж connect. Це навіть не оператор JavaScript, якщо я не помиляюся.

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

Оновлення:

Насправді це частина, react-reduxяка використовується для підключення компонента React до магазину Redux.


6
Я не знайомий з Redux, але він схожий на декоратора. medium.com/google-developers/…
Лі

4
Мені подобається, як у цьому новому світі JavaScript ти дивишся на кодову половину часу і думаєш, "яка це частина синтаксису мови?"
МК.

4
Лол, я зараз заглиблююся в редукс та інше. Але тоді я не знав, що синтаксис декоратора не має нічого спільного з редукцією. Це просто JavaScript. Радий бачити, що це питання допомагає багатьом людям, як я. :)
Салман

1
Очевидно команда redux відлякує використання підключення як декоратора на даний момент github.com/happypoulp/redux-tutorial/isissue/87
Syed

Відповіді:


376

@Символ в дійсності вираз JavaScript пропонується в даний час для позначення декораторів :

Декоратори дозволяють коментувати та змінювати класи та властивості під час проектування.

Ось приклад налаштування Redux без і з декоратором:

Без декоратора

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

Використання декоратора

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
}

Обидва приклади вище рівнозначні, це лише питання переваги. Крім того, синтаксис декоратора ще не вбудований у будь-який час виконання Javascript і все ще експериментальний і може змінюватися. Якщо ви хочете використовувати його, він доступний за допомогою Babel .


46
це приголомшливо
svnm

2
Можна навіть бути більш стислим із синтаксисом ES6. @connect (state => {return {todos: state.todos};}, відправка => {return {дії: bindActionCreators (actionCreators, відправка)};})
LessQuesar

11
Якщо ви дійсно хочете бути стислими, ви можете використовувати неявні повернення в ES6. Це залежить від того, наскільки явним ви хочете бути. @connect(state => ({todos: state.todos}), dispatch => ({actions: bindActionCreators(actionCreators, dispatch)}))
Таннер Семерад

3
Як би ви експортували непоєднаний компонент для тестування одиниць?
час

Використання декоратора для скорочення та реагування-навігація може бути проблематичним, поточна найкраща практика полягає у використанні функції не декоратора: github.com/react-community/react-navigation/isissue/1180
straya

50

Дуже важливо!

Ці реквізити називаються реквізитом стану, і вони відрізняються від звичайних реквізитів, будь-яка зміна реквізиту стану компонента викликає метод візуалізації компонентів знову і знову, навіть якщо ви не використовуєте ці реквізити, тому для причин продуктивності намагайтеся прив’язати лише до свого компонента. реквізити стану, які вам потрібні всередині вашого компонента, і якщо ви використовуєте допоміжний реквізит, зв'язуйте лише ці реквізити.

Приклад: давайте сказати, що всередині вашого компонента вам потрібні лише два реквізити:

  1. останнє повідомлення
  2. ім'я користувача

не роби цього

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

зробити це

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

9
або використовувати селектори, як переобирати або швидко пам’ятати
Julius Koronci

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