Apa '@' (pada simbol) di dekorator Redux @connect?

226

Saya belajar Redux dengan Bereaksi dan menemukan kode ini. Saya tidak yakin apakah itu Redux khusus atau tidak, tetapi saya telah melihat potongan kode berikut dalam salah satu contoh.

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

Sementara fungsionalitasnya connectcukup mudah, tapi saya tidak mengerti @sebelumnya connect. Bahkan bukan operator JavaScript jika saya tidak salah.

Dapatkah seseorang menjelaskan tolong apa ini dan mengapa ini digunakan?

Memperbarui:

Itu sebenarnya bagian react-reduxyang digunakan untuk menghubungkan komponen Bereaksi ke toko Redux.

Salman
sumber
6
Saya tidak terbiasa dengan Redux, tetapi sepertinya dekorator. medium.com/google-developers/…
Lee
4
Saya suka bagaimana di dunia JavaScript baru ini Anda menatap kode setengah dari waktu dan berpikir "apa bagian dari sintaks bahasa ini?"
MK.
4
Lol, saya jauh ke redux dan semacamnya sekarang. Tapi saat itu saya tidak tahu sintaks dekorator tidak ada hubungannya dengan redux. Ini hanya JavaScript. Senang melihat pertanyaan ini membantu banyak orang seperti saya. :)
Salman
1
Rupanya tim redux mengecilkan penggunaan koneksi sebagai dekorator saat ini github.com/happypoulp/redux-tutorial/issues/87
Syed Jafri

Jawaban:

376

The @simbol sebenarnya ekspresi JavaScript saat ini diusulkan untuk menandakan dekorator :

Dekorator memungkinkan untuk membuat anotasi dan memodifikasi kelas dan properti pada waktu desain.

Berikut adalah contoh pengaturan Redux tanpa dan dengan dekorator:

Tanpa dekorator

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

Menggunakan dekorator

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
}

Kedua contoh di atas setara, hanya masalah preferensi. Juga, sintaksis dekorator belum dibangun ke dalam runtime Javascript apa pun, dan masih bersifat eksperimental dan dapat berubah. Jika Anda ingin menggunakannya, itu tersedia menggunakan Babel .

Tanner Semerad
sumber
46
ini luar biasa
svnm
2
Satu bahkan bisa lebih singkat dengan sintaks ES6. @connect (state => {return {todos: state.todos};}, dispatch => {return {action: bindActionCreators (actionCreators, dispatch)};})
LessQuesar
11
Jika Anda benar-benar ingin terse Anda dapat menggunakan pengembalian implisit di ES6. Tergantung pada seberapa eksplisit Anda ingin menjadi. @connect(state => ({todos: state.todos}), dispatch => ({actions: bindActionCreators(actionCreators, dispatch)}))
Tanner Semerad
3
Bagaimana Anda mengekspor komponen yang tidak terhubung untuk pengujian unit?
tim
Menggunakan dekorator untuk redux dengan navigasi reaksi bisa bermasalah, praktik terbaik saat ini adalah menggunakan fungsi bukan dekorator: github.com/react-community/react-navigation/issues/1180
straya
50

Sangat penting!

Alat peraga ini disebut alat peraga keadaan dan mereka berbeda dari alat peraga normal, setiap perubahan pada alat peraga keadaan komponen Anda akan memicu metode render komponen berulang kali bahkan jika Anda tidak menggunakan alat peraga ini sehingga untuk Alasan Kinerja cobalah untuk mengikat hanya ke komponen Anda keadaan alat peraga yang Anda butuhkan di dalam komponen Anda dan jika Anda menggunakan sub alat peraga hanya mengikat alat peraga ini.

contoh: katakanlah di dalam komponen Anda, Anda hanya perlu dua alat peraga:

  1. pesan terakhir
  2. nama pengguna

jangan lakukan ini

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

melakukan hal ini

@connect(state => ({ 
   user_name: state.user.name,
   last_message: state.messages[state.messages.length-1]
}))
Fareed Alnamrouti
sumber
9
atau gunakan penyeleksi seperti pilih kembali atau fastmemoize
Julius Koronci