Nó có nghĩa là gì ... phần còn lại trong React JSX


82

Nhìn vào ví dụ React Router Dom v4 này https://reacttraining.com/react-router/web/example/auth-workflow, tôi thấy rằng thành phần PrivateRoute phá hủy một phần còn lại như thế này

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)

Tôi muốn chắc chắn rằng điều đó { component: Component, ...rest }có nghĩa là:

Từ đó props, lấy phần hỗ trợ Thành phần và sau đó là tất cả các đạo cụ khác được cung cấp cho bạn và đổi tên propsthành restđể bạn có thể tránh các vấn đề về đặt tên với các đạo cụ được chuyển cho renderhàm Tuyến

Tôi nói đúng chứ?


5
Đó là một tổ chức phi tiêu chuẩn được nêu ra cú pháp quy định tại github.com/tc39/proposal-object-rest-spread
zerkms

Câu trả lời:


155

Xin lỗi, tôi nhận ra câu trả lời đầu tiên của mình (trong khi hy vọng vẫn cung cấp ngữ cảnh hữu ích / bổ sung) không trả lời câu hỏi của bạn. Hãy để tôi thử lại.

Bạn hỏi:

Tôi muốn chắc chắn rằng điều đó { component: Component, ...rest }có nghĩa là:

Từ props, nhận chỗ dựa Componentvà sau đó là tất cả những thứ khác propsđược cung cấp cho bạn, và đổi tên propsthành restđể bạn có thể tránh các vấn đề đặt tên với hàm propsđược chuyển cho renderhàm Route

Diễn giải của bạn không hoàn toàn đúng. Tuy nhiên, dựa trên suy nghĩ của bạn, có vẻ như bạn ít nhất cũng biết thực tế rằng những gì đang xảy ra ở đây tương đương với một số loại cấu trúc đối tượng (xem câu trả lời thứ hai và nhận xét ở đó để làm rõ hơn).

Để đưa ra lời giải thích chính xác, hãy chia { component: Component, ...rest }biểu thức thành hai phép toán riêng biệt:

  1. Thao tác 1: Tìm thuộc componenttính được xác định trên props( Lưu ý : c omponent viết thường ) và gán nó vào một vị trí mới ở trạng thái mà chúng ta gọi là Component( Lưu ý : viết hoa C omponent).
  2. Thao tác 2: Sau đó, lấy tất cả các thuộc tính còn lại được xác định trên propsđối tượng và thu thập chúng bên trong một đối số được gọi rest.

Điểm quan trọng là bạn KHÔNG đổi tên propsthành rest. (Và nó cũng không liên quan đến việc cố gắng "tránh các vấn đề đặt tên với hàm propsđược truyền cho renderhàm Route ".)

rest === props;
// => false

Bạn chỉ đơn giản là rút phần còn lại (do đó tại sao đối số được đặt tên như vậy) của các thuộc tính được xác định trên propsđối tượng của bạn thành một đối số mới được gọi rest.


Ví dụ sử dụng

Đây là một ví dụ. Giả sử chúng ta có một đối tượng `myObj` được định nghĩa như sau:
const myObj = {
  name: 'John Doe',
  age: 35,
  sex: 'M',
  dob: new Date(1990, 1, 1)
};

Đối với ví dụ này, có thể hữu ích nếu bạn nghĩ về propsviệc có cùng cấu trúc ( tức là các thuộc tính và giá trị) như được hiển thị trong myObj. Bây giờ, chúng ta hãy viết bài tập sau.

const { name: Username, ...rest } = myObj

Câu lệnh trên tương ứng với cả việc khai báogán hai biến (hoặc, tôi đoán là hằng số). Tuyên bố có thể được coi là:

Lấy thuộc tính nameđược xác định trên myObjvà gán giá trị của nó cho một biến mới mà chúng tôi gọi Username. Sau đó, phải mất bất cứ điều gì các tài sản khác được xác định trên myObj( tức là , age, sexdob) và thu thập chúng vào một đối tượng mới được gán cho tên biến chúng ta rest.

Logging Usernamerestđến consolesẽ xác nhận điều này. Chúng tôi có những điều sau:

console.log(Username);
// => John Doe
console.log(rest);
// => { age: 35, sex: 'M', dob: Mon Jan 01 1990 00:00:00 GMT-0800 (PST) }

Ghi chú bên lề

Bạn có thể tự hỏi:

Tại sao lại gặp khó khăn khi rút componenttài sản ra chỉ để đổi tên nó Componentbằng một chữ cái in hoa "C"?

Vâng, nó có vẻ khá tầm thường. Và, mặc dù nó là một thực hành React tiêu chuẩn, nhưng có một lý do tại sao tất cả các tài liệu của Facebook về framework của nó đều được viết như vậy. Cụ thể, việc viết hoa các thành phần tùy chỉnh được hiển thị bằng JSX không phải là một thực tiễn mà nó là một điều cần thiết. React hay nói đúng hơn là JSX phân biệt chữ hoa chữ thường . Các thành phần tùy chỉnh được chèn mà không có chữ cái đầu tiên viết hoa sẽ không được hiển thị cho DOM. Đây chỉ là cách React đã tự định nghĩa để xác định các thành phần tùy chỉnh. Như vậy, có ví dụ không đổi tên bổ sung các componenttài sản đó đã được kéo ra khỏi propsđến Component, các <component {...props} />biểu hiện sẽ không hiển thị đúng.


5
lời giải thích tuyệt vời cho chúng tôi noobies!
user2763557 20/09/19

13

Nó cho phép bạn "truyền bá" tất cả của bạn propstrong một biểu thức ngắn gọn duy nhất. Ví dụ: giả sử thành phần propscủa bạn nhận được PrivateRoutetrông giống như

// `props` Object:
{
  thing1: 'Something',
  thing2: 'Something else'
}

Nếu bạn muốn thêm tay tắt các mặt hàng này ( ví dụ , thing1thing2) xuống lồng nhau <Component />thẻ và bạn chưa quen thuộc với các đối tượng lây lan cú pháp, bạn có thể viết:

<Component
  thing1={ props.thing1 }
  thing2={ props.thing2 } />

Tuy nhiên, { ...props }cú pháp obviates cách rườm rà như vậy bằng cách cho phép bạn để lây lan của propsđối tượng trong một cách tương tự có thể lây lan một mảng các giá trị ( ví dụ , [...vals]). Nói cách khác, biểu thức JSX bên dưới và bên trên hoàn toàn tương đương.

<Component { ...props } />

1
Trong khi có liên quan, đừng trộn cú pháp lây lan của JSX với các thuộc tính còn lại .
Felix Kling

3
"Nó cho phép bạn" truyền bá "tất cả các đạo cụ của mình trong một biểu thức ngắn gọn duy nhất." Điều đó không đúng. ...resttrong { component: Component, ...rest } thu thập tất cả các thuộc tính khác trong đối tượng rest. Câu hỏi đặt ra là về ...rest, không{...props}
Felix Kling

Như Felix lưu ý, có sự phân biệt giữa toán tử trải đối tượng (không chuẩn) trong JSX và toán tử trải phổ _ / _ còn lại như được định nghĩa trong đặc tả ECMAScript 2015. Đối với một điều, cố gắng viết một cái gì đó như { ...myObj }trong một môi trường không phải React ( ví dụ: bảng điều khiển trình duyệt) sẽ tạo ra một SyntaxError. Tuy nhiên, phần còn lại _ / _ lây lan của ES6 cung cấp một khuôn khổ khái niệm hữu ích để suy nghĩ về sự lây lan đối tượng của JSX .
IsenrichO

4

Hãy đơn giản hóa nó: trong JavaScript, nếu một cặp "key: value" giống nhau, obj={account:account}thì giống như obj={account}. Vì vậy, khi chuyển các đạo cụ từ thành phần mẹ sang thành phần con:

const Input = ({name,label,error, ...rest}) => {
  return (
    <div className="form-group">
      <label htmlFor={name}>{label}</label>
      <input
        {...rest}
        autoFocus
        name={name}
        id={name}
        className="form-control"
        aria-describedby="emailHelp"
      />
    </div>
  );
};
export default Input;

bạn sẽ chuyển phần còn lại của các đạo cụ như:

label={label} placeholder={placeholder} type={type}
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.