Có gì khác biệt giữa siêu super () và siêu (đạo cụ) của Hồi giáo trong React khi sử dụng các lớp es6?


Câu trả lời:


710

Chỉ có một lý do khi người ta cần phải vượt qua propsđểsuper() :

Khi bạn muốn truy cập this.props trong constructor.

Đi qua:

class MyComponent extends React.Component {    
    constructor(props) {
        super(props)

        console.log(this.props)
        // -> { icon: 'home', … }
    }
}

Không qua

class MyComponent extends React.Component {    
    constructor(props) {
        super()

        console.log(this.props)
        // -> undefined

        // Props parameter is still available
        console.log(props)
        // -> { icon: 'home', … }
    }

    render() {
        // No difference outside constructor
        console.log(this.props)
        // -> { icon: 'home', … }
    }
}

Lưu ý rằng đi hay không đi qua propsđể superkhông có ảnh hưởng trên việc sử dụng sau này của this.propsbên ngoài constructor. Đó là render, shouldComponentUpdatehoặc xử lý sự kiện luôn có quyền truy cập vào nó.

Điều này được nói rõ ràng trong một câu trả lời của Sophie Alpert cho một câu hỏi tương tự.


Tài liệu về Nhà nước và Vòng đời của Haiti, Thêm trạng thái cục bộ vào một lớp, điểm 2 Lời khuyên:

Các thành phần lớp nên luôn luôn gọi hàm tạo cơ sở với props.

Tuy nhiên, không có lý do được cung cấp. Chúng tôi có thể suy đoán đó là do phân lớp hoặc để tương thích trong tương lai.

(Cảm ơn @MattBrowne vì liên kết)


16
Tôi nghĩ bạn đúng, mặc dù các câu trả lời khác nhận được nhiều phiếu hơn. this.propsundefinedtrừ khi được thông qua super(). Dù bằng cách nào, nó không ảnh hưởng sau render hoặc sẵn có của this.propstrong render()chức năng.
Kính hiển vi

3
@Rotareti, không, thực sự phần còn lại của lớp không phụ thuộc vào cấu trúc này, đó là điểm. Thành phần nhận đạo cụ theo một cách khác mà theo tham số của hàm tạo. Và vì bạn chuyển các đạo cụ ban đầu cho super, bạn có tham chiếu đến chúng trong hàm tạo.
Robin Pokorny

7
Theo tài liệu React, bạn phải luôn chuyển propsđến super(): facebook.github.io/react/docs/ mẹo . Tôi không chắc tại sao, vì như bạn chỉ ra this.propscó thể truy cập được bằng các phương thức khác ... có lẽ họ đang khuyến nghị điều này để tương thích trong tương lai trong trường hợp các phiên bản tương lai của React có thể muốn làm gì đó với propshàm tạo?
Matt Browne

23
Có lẽ tôi chỉ mở một lon sâu ở đây, nhưng tại sao bao giờ vượt qua propsđể superkhi nào, như bạn chỉ ra, các propstham số là phải có sẵn để chúng ta sử dụng trong các nhà xây dựng , và this.propscác công trình ở khắp mọi nơi khác? Có một lợi ích ở tất cả để sử dụng this.propstrên chỉ props? Có phải là thực tế xấu để phá hủy propscấu trúc trong các nhà xây dựng? Tôi nghĩ rằng tôi vẫn thất bại trong việc nhìn thấy một trường hợp khi bạn muốn bao giờ cần phải vượt qua propsđể super, nhưng tôi sẵn sàng đặt cược nó chỉ là sự thiếu hiểu biết của tôi, ha.
indiesquidge

9
Nếu bạn sử dụng super(props), bạn có thể gọi các phương thức sử dụng this.props từ hàm tạo , như this.doStuffUsingThisDotProps(), mà không phải truyền tham số đạo cụ cho các phương thức / hàm đó. Tôi chỉ viết một constructor làm điều này, mà dường như sẽ yêu cầu tôi sử dụng super(props)đầu tiên, theo các câu trả lời cho câu hỏi này.
Victor Zamanian

54

Trong ví dụ này, bạn đang mở rộng React.Componentlớp và theo thông số ES2015, một hàm tạo của lớp con không thể sử dụng thischo đến khi super()được gọi; Ngoài ra, các hàm tạo của lớp ES2015 phải gọi super()nếu chúng là các lớp con.

class MyComponent extends React.Component {
  constructor() {
    console.log(this); // Reference Error
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Ngược lại:

class MyComponent extends React.Component {
  constructor() {
    super();
    console.log(this); // this logged to console
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Chi tiết hơn theo câu trả lời tràn ngăn xếp tuyệt vời này

Bạn có thể thấy các ví dụ về các thành phần được tạo bằng cách mở rộng React.Componentlớp không gọi super()nhưng bạn sẽ nhận thấy những thành phần này không có constructor, do đó không cần thiết.

class MyOtherComponent extends React.Component {
  render() {
    return <div>Hi {this.props.name}</div>;
  }
}

Một điểm khó hiểu mà tôi đã thấy từ một số nhà phát triển mà tôi đã nói đến là các thành phần không có constructorvà do đó không gọi được ở super()bất cứ đâu, vẫn có this.propssẵn trong render()phương thức. Hãy nhớ rằng quy tắc này và điều này cần tạo ra một thisràng buộc constructorchỉ áp dụng cho constructor.


15
Cảm ơn rất nhiều vì câu trả lời của bạn, nhưng nó không trả lời câu hỏi ban đầu của tôi (sự khác biệt giữa super()super(props)).
Misha Moroshko

46

Khi bạn vượt qua propsđể super, đạo cụ được giao nhiệm vụ this. Hãy xem kịch bản sau đây:

constructor(props) {
    super();
    console.log(this.props) //undefined
}

Bao giờ khi bạn làm:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}

Câu trả lời tốt nhất trong danh sách.
Basavaraj Hadimani

Câu trả lời này đúng một nửa, Ví dụ này chỉ dành cho phương thức constructor. Ví dụ: ngay cả khi bạn không viết siêu (đạo cụ), this.props theo phương thức kết xuất vẫn sẽ được chỉ định và khả dụng. Lý do duy nhất được đề cập ở trên là khi sử dụng this.props trong hàm tạo.
48 phút

12

Theo mã nguồn

function ReactComponent(props, context) {
  this.props = props;
  this.context = context;
}

bạn phải vượt qua propsmỗi khi bạn có đạo cụ và bạn không đặt chúng vào this.propsbằng tay.


1
Tôi vẫn chưa rõ về điều này. nếu bạn nhìn vào những hai thành phần , bạn có thể thấy một cuộc gọi super(props)và người kia thì không. Nhưng người tiêu dùng của họ đều đặt đạo cụ. Sự khác biệt là gì?
Kyeotic

Điều này có nghĩa là this.props = propssuper(props)điều tương tự?
reectrix

1
Đây không phải là sự thật. ReactEuity thực sự thiết lập this.propstừ 'bên ngoài' bất kể những gì được thực hiện trong hàm tạo.
Robin Pokorny

11

Dan Abramov đã viết một bài viết về chủ đề này:

Tại sao chúng ta viết siêu (đạo cụ)?

Và ý chính của nó là thật hữu ích khi có thói quen vượt qua nó để tránh kịch bản này, thành thật mà nói, tôi không thấy điều đó khó xảy ra:

// Inside React
class Component {
  constructor(props) {
    this.props = props;
    // ...
  }
}

// Inside your code
class Button extends React.Component {
  constructor(props) {
    super(); // 😬 We forgot to pass props
    console.log(props);      // ✅ {}
    console.log(this.props); // 😬 undefined 
  }
  // ...
}

8

super() được sử dụng để gọi hàm tạo.

super(props) sẽ vượt qua props đến hàm tạo cha.

Từ ví dụ của bạn, super(props)sẽ gọi hàm React.Componenttạo đi vàoprops làm đối số.

Thông tin thêm về super: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super


18
Vâng, đó là những gì nó làm. Nhưng tại sao ? Và khi nào thì một trong hai hình thức được yêu cầu trong React?
Bergi

7

Khi thực hiện constructor()chức năng bên trong một thành phần React, super()là một yêu cầu. Hãy nhớ rằng MyComponentthành phần của bạn đang mở rộng hoặc mượn chức năng từ React.Componentlớp cơ sở.

Lớp cơ sở này có một constructor()chức năng của riêng nó có một số mã bên trong nó, để thiết lập thành phần React cho chúng ta.

Khi chúng ta định nghĩa một constructor()hàm bên trong MyComponentlớp, về cơ bản, chúng ta sẽ ghi đè hoặc thay thế constructor()hàm bên trong React.Componentlớp, nhưng chúng ta vẫn cần đảm bảo rằng tất cả mã thiết lập bên trong nàyconstructor() hàm vẫn được gọi.

Vì vậy, để đảm bảo rằng các React.Component's constructor()chức năng được gọi là, chúng ta gọi là super(props). super(props)là một tham chiếu đến constructor()chức năng của cha mẹ , đó là tất cả.

Chúng ta phải thêm super(props)mỗi lần chúng ta định nghĩa một constructor()hàm bên trong một thành phần dựa trên lớp.

Nếu chúng ta không, chúng ta sẽ thấy một lỗi nói rằng chúng ta phải gọi super(props).

Toàn bộ lý do để xác định constructor()funciton này là để khởi tạo đối tượng trạng thái của chúng ta.

Vì vậy, để khởi tạo đối tượng trạng thái của chúng ta, bên dưới siêu cuộc gọi tôi sẽ viết:

class App extends React.Component {
  constructor(props) {
      super(props);

      this.state = {};
   }

  // React says we have to define render()
  render() {
    return <div>Hello world</div>;
  }
};

Vì vậy, chúng tôi đã xác định constructor()phương thức của mình, khởi tạo đối tượng trạng thái bằng cách tạo đối tượng JavaScript, gán một thuộc tính hoặc cặp khóa / giá trị cho nó, gán kết quả của điều đó cho this.state. Bây giờ tất nhiên đây chỉ là một ví dụ ở đây vì vậy tôi chưa thực sự gán một cặp khóa / giá trị cho đối tượng trạng thái, nó chỉ là một đối tượng trống.


4

Đây là câu đố tôi đã thực hiện: jsfiddle.net . Nó cho thấy rằng các đạo cụ được gán không có trong hàm tạo theo mặc định. Theo tôi hiểu họ đang khẳng định trong phương pháp React.createElement. Do đó super(props)nên được gọi là chỉ khi assings constructor tay của lớp cha propsđến this.props. Nếu bạn chỉ mở rộng React.Componentcuộc gọi super(props)sẽ không làm gì với đạo cụ. Có lẽ nó sẽ được thay đổi trong các phiên bản tiếp theo của React.


3

Ở đây chúng ta sẽ không nhận được cái này trong hàm tạo nên nó sẽ trả về không xác định, nhưng chúng ta sẽ có thể tìm nạp cái này bên ngoài hàm constructor

class MyComponent extends React.Component {
  constructor() {
    console.log(this); // Reference Error i.e return undefined
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Nếu chúng ta đang sử dụng super (), thì chúng ta cũng có thể tìm nạp biến "this" bên trong hàm tạo

class MyComponent extends React.Component {
  constructor() {
    super();
    console.log(this); // this logged to console
  }

  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

Vì vậy, khi chúng ta đang sử dụng super (); chúng ta sẽ có thể tìm nạp cái này nhưng this.props sẽ không được xác định trong hàm tạo. Nhưng khác với constructor, this.props sẽ không trả về không xác định.

Nếu chúng ta sử dụng siêu (đạo cụ), thì chúng ta cũng có thể sử dụng giá trị this.props bên trong hàm tạo

Câu trả lời của Sophie Alpert

Nếu bạn muốn sử dụng this.props trong constructor, bạn cần truyền đạo cụ cho super. Mặt khác, nó không thành vấn đề vì React đặt .props vào ví dụ từ bên ngoài ngay sau khi gọi hàm tạo.


3

Đối với phiên bản phản ứng 16.6.3, chúng tôi sử dụng siêu (đạo cụ) để khởi tạo tên thành phần trạng thái : this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
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.