'@' (Biểu tượng) trong trang trí Redux @connect là gì?


226

Tôi đang học Redux với React và tình cờ thấy mã này. Tôi không chắc nó có phải là Redux cụ thể hay không, nhưng tôi đã thấy đoạn mã sau đây trong một trong các ví dụ.

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

Mặc dù chức năng của connectnó khá đơn giản, nhưng tôi không hiểu @trước đây connect. Nó thậm chí không phải là một toán tử JavaScript nếu tôi không sai.

Ai đó có thể giải thích xin vui lòng đây là gì và tại sao nó được sử dụng?

Cập nhật:

Trên thực tế, đây là một phần react-reduxđược sử dụng để kết nối thành phần React với cửa hàng Redux.


6
Tôi không quen thuộc với Redux, nhưng nó trông giống như một vật trang trí. Medium.com/google-developers/ Kẻ
Lee

4
Tôi thích làm thế nào trong thế giới JavaScript mới này, bạn đang nhìn chằm chằm vào mã một nửa thời gian và suy nghĩ "phần nào của cú pháp ngôn ngữ này là gì?"
MK.

4
Lol, tôi đang đi sâu vào redux và công cụ bây giờ. Nhưng hồi đó tôi không biết cú pháp trang trí không liên quan gì đến redux. Nó chỉ là JavaScript. Vui mừng khi thấy câu hỏi này đang giúp rất nhiều người như tôi. :)
Salman

1
Rõ ràng nhóm redux không khuyến khích việc sử dụng kết nối như một người trang trí tại thời điểm github.com/happypoulp/redux-tutorial/issues/87
Syed Jafri

Câu trả lời:


376

Các @biểu tượng là trong thực tế một biểu thức JavaScript hiện đề xuất để biểu thị trang trí :

Nhà trang trí làm cho nó có thể chú thích và sửa đổi các lớp và thuộc tính tại thời điểm thiết kế.

Đây là một ví dụ về việc thiết lập Redux mà không cần và có trang trí:

Không có người trang trí

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

Sử dụng một trang trí

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
}

Cả hai ví dụ trên đều tương đương nhau, đó chỉ là vấn đề ưu tiên. Ngoài ra, cú pháp trang trí chưa được tích hợp trong bất kỳ thời gian chạy Javascript nào và vẫn đang thử nghiệm và có thể thay đổi. Nếu bạn muốn sử dụng nó, nó có sẵn bằng Babel .


46
điều này thật tuyệt
svnm

2
Một thậm chí có thể ngắn gọn hơn với cú pháp ES6. @connect (state => {return {todos: state.todos};}, công văn => {return {hành động: bindActionCreators (actionCreators, công văn)};})
LessQuesar

11
Nếu bạn thực sự muốn ngắn gọn, bạn có thể sử dụng trả về ngầm trong ES6. Nó phụ thuộc vào cách bạn muốn rõ ràng. @connect(state => ({todos: state.todos}), dispatch => ({actions: bindActionCreators(actionCreators, dispatch)}))
Tanner Semerad

3
Làm thế nào bạn sẽ xuất thành phần chưa được kết nối để thử nghiệm đơn vị?
tim

Sử dụng trang trí cho redux với điều hướng phản ứng có thể có vấn đề, thực tiễn tốt nhất hiện nay là sử dụng chức năng không phải là trang trí: github.com/react-community/react-navlation/issues/1180
straya

50

Rất quan trọng!

Các đạo cụ này được gọi là đạo cụ trạng thái và chúng khác với đạo cụ thông thường, mọi thay đổi đối với đạo cụ trạng thái thành phần của bạn sẽ kích hoạt phương thức kết xuất thành phần nhiều lần ngay cả khi bạn không sử dụng các đạo cụ này vì vậy Lý do hiệu suất chỉ cố gắng liên kết với thành phần của bạn các đạo cụ trạng thái mà bạn cần bên trong thành phần của mình và nếu bạn sử dụng một đạo cụ phụ chỉ ràng buộc các đạo cụ này.

ví dụ: giả sử bên trong thành phần của bạn, bạn chỉ cần hai đạo cụ:

  1. tin nhắn cuối cùng
  2. tên người dùng

đừng làm điều này

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

làm cái này

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

9
hoặc sử dụng các công cụ chọn như chọn lại hoặc fastmemoize
Julius Koronci

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.