Phản ứng thành phần khởi tạo trạng thái từ đạo cụ


204

Trong React, có sự khác biệt thực sự nào giữa hai triển khai này không? Một số người bạn nói với tôi rằng FirstComponent là mẫu, nhưng tôi không hiểu tại sao. SecondComponent có vẻ đơn giản hơn vì kết xuất chỉ được gọi một lần.

Đầu tiên:

import React, { PropTypes } from 'react'

class FirstComponent extends React.Component {

  state = {
    description: ''
  }

  componentDidMount() {
    const { description} = this.props;
    this.setState({ description });
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} /> 
    );
  }
}

export default FirstComponent;

Thứ hai:

import React, { PropTypes } from 'react'

class SecondComponent extends React.Component {

  state = {
    description: ''
  }

  constructor (props) => {
    const { description } = props;
    this.state = {description};
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} />   
    );
  }
}

export default SecondComponent;

Cập nhật: Tôi đã thay đổi setState () thành this.state = {} (cảm ơn joews), tuy nhiên, tôi vẫn không thấy sự khác biệt. Là một trong những tốt hơn so với khác?


10
Tại sao bạn lưu trữ đạo cụ của bạn trong tiểu bang? Bạn nên sử dụng đạo cụ của mình trực tiếp thay vì lưu trữ một giá trị. Hãy đọc Tại sao Đặt Đạo cụ làm Trạng thái trong React.js là Sự báng bổĐạo cụ trong getInitialState là một Mô hình Chống .
Aurora0001

12
Một ví dụ - một thành phần có thể bật (ví dụ: popover hoặc ngăn kéo). Phụ huynh biết thành phần nên bắt đầu mở hay đóng; thành phần có thể biết liệu nó có mở hay không tại một thời điểm. Trong trường hợp đó tôi nghĩ this.state = { isVisible: props.isVisible }có ý nghĩa. Phụ thuộc vào cách ứng dụng phân phối trạng thái UI.
tham gia

2
Bạn nên đọc phương tiện này.com / @ justintulk / trộm
FDisk

5
Năm 2017, Facebook trình diễn sử dụng đạo cụ để đặt trạng thái ban đầu trong tài liệu của họ: Reacjs.org/docs/react-component.html#constructor
Rohmer

1
@ Aurora0001 Trong trường hợp bạn cần xử lý một biểu mẫu, hãy nói một biểu mẫu chỉnh sửa sẽ tự thực hiện các yêu cầu mạng nhưng bạn cần khởi tạo các đầu vào với các giá trị sẽ trở thành đạo cụ cho thành phần đó. Để giữ cho biểu mẫu động, các giá trị đó phải được giữ ở trạng thái.
Eric McWinNEr

Câu trả lời:


196

Cần lưu ý rằng đó là một mô hình chống sao chép các thuộc tính không bao giờ thay đổi sang trạng thái (chỉ cần truy cập trực tiếp .props trong trường hợp đó). Nếu cuối cùng bạn có một biến trạng thái sẽ thay đổi nhưng bắt đầu bằng một giá trị từ .props, bạn thậm chí không cần một lệnh gọi hàm tạo - các biến cục bộ này được khởi tạo sau một lệnh gọi đến hàm tạo của cha mẹ:

class FirstComponent extends React.Component {
  state = {
    x: this.props.initialX,
    // You can even call functions and class methods:
    y: this.someMethod(this.props.initialY),
  };
}

Đây là một tốc ký tương đương với câu trả lời từ @joews bên dưới. Nó dường như chỉ hoạt động trên các phiên bản mới hơn của bộ chuyển đổi es6, tôi đã gặp vấn đề với nó trên một số thiết lập webpack. Nếu điều này không phù hợp với bạn, bạn có thể thử thêm plugin babel babel-plugin-transform-class-propertieshoặc bạn có thể sử dụng phiên bản không viết tắt của @joews bên dưới.


1
bạn có thể giải thích thêm câu trả lời của bạn khác với câu trả lời của @joews như thế nào không?
Jalal

3
Đã thêm "Bạn có thể bỏ qua lệnh gọi hàm tạo nếu tất cả những gì bạn đang làm là đặt biến."
Zane Hooper

3
Nếu nó không hoạt động, có lẽ bạn cần phải cài đặt plugin babel này "babel-plugin-Transform-class-property".
Faheem

2
Nó không phải là một mô hình chống khởi tạo trạng thái từ các đạo cụ nếu nó hiểu rằng trạng thái đó không dựa vào các đạo cụ sau khi khởi tạo. Nếu bạn đang cố gắng giữ cho cả hai đồng bộ, đó là một kiểu chống.
Yatrix

1
@ ak85 đó là cùng một cú pháp nhưng thay vào đó bạn sẽ sử dụng this.state. Cú pháp này chỉ là một cú pháp tốc ký để thiết lập trạng thái trong quá trình xây dựng lớp (và cũng có thể được sử dụng cho các biến khác ngoài trạng thái)
Zane Hooper

137

Bạn không cần phải gọi setStatetrong Thành phần constructor- thật đơn giản để đặt this.statetrực tiếp:

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      x: props.initialX
    };
  }
  // ...
}

Xem tài liệu React - Thêm trạng thái cục bộ vào một lớp .

Không có lợi thế cho phương pháp đầu tiên bạn mô tả. Nó sẽ dẫn đến một bản cập nhật thứ hai ngay lập tức trước khi gắn thành phần lần đầu tiên.


4
Câu trả lời tốt. Có thể đáng lưu ý rằng điều này chỉ để thiết lập trạng thái ban đầu; bạn vẫn cần sử dụng setStatenếu bạn thay đổi nó ở bất kỳ điểm nào khác, nếu không các thay đổi có thể không hiển thị.
Aurora0001

Cảm ơn một lần nữa jowes, thứ hai tài liệu facebook.github.io/react/docs/
Levy Moreira


1
Trên một lưu ý cận biên: sử dụng super(props)trong hàm tạo. Thảo luận về SO
cutemachine

2
đề xuất của joews hoạt động trong hầu hết các trường hợp, nhưng hãy cẩn thận về việc gửi đạo cụ tới this.state trực tiếp. Sao chép đạo cụ vào this.state thực sự là một nguồn duy nhất của sự thật ( Medium.com/react-ecystem/, ). Ngoài ra, Dan Abramov từng đề nghị không lưu trữ các giá trị đạo cụ ở trạng thái. ( twitter.com/dan_abramov/status/749710501916139520/photo/1 ).
Hiroki

33

Cập nhật cho React 16.3 alpha được giới thiệu static getDerivedStateFromProps(nextProps, prevState)( tài liệu ) thay thế cho componentWillReceiveProps.

getDerivingStateFromProps được gọi sau khi một thành phần được khởi tạo cũng như khi nó nhận được các đạo cụ mới. Nó sẽ trả về một đối tượng để cập nhật trạng thái hoặc null để chỉ ra rằng các đạo cụ mới không yêu cầu bất kỳ cập nhật trạng thái nào.

Lưu ý rằng nếu một thành phần cha mẹ khiến thành phần của bạn hiển thị lại, phương thức này sẽ được gọi ngay cả khi đạo cụ không thay đổi. Bạn có thể muốn so sánh các giá trị mới và trước đây nếu bạn chỉ muốn xử lý các thay đổi.

https://reactjs.org/docs/react-component.html#static-getderivingstatefromprops

Nó là tĩnh, do đó nó không có quyền truy cập trực tiếp this(tuy nhiên nó có quyền truy cập prevState, có thể lưu trữ những thứ thường được gắn vào thisví dụ refs)

được chỉnh sửa để phản ánh sự điều chỉnh của @ nerfologist trong các bình luận


3
Chỉ cần làm rõ, nó được đặt tên getDerivedStateFromProps(đánh dấu chữ in hoa trong Đạo cụ) và các thông số là nextProps, prevState(không nextState): Reacjs.org/docs/iêu
nghiên cứu khoa học

1
Ồ chúng ta có thể sử dụng điều này để cập nhật trạng thái khi nhận được đạo cụ cập nhật !
Aromal Sasidharan

2
Chúng ta vẫn phải tạo trạng thái ban đầu trong hàm tạo, xem xét rằng trạng thái getDerivedStateFromPropsluôn được gọi trước khi kết xuất ban đầu?
bvdb

19

Bạn có thể sử dụng biểu mẫu ngắn như dưới đây nếu bạn muốn thêm tất cả đạo cụ vào trạng thái và giữ nguyên tên.

constructor(props) {
    super(props);
    this.state = {
       ...props
    }
    //...
}

1
nó là một mô hình chống sao chép các thuộc tính không bao giờ thay đổi sang trạng thái. Tốt hơn là mô tả rõ ràng những lĩnh vực mà thành phần của bạn sử dụng.
Michael Freidgeim

5

thiết lập dữ liệu trạng thái bên trong hàm tạo như thế này

constructor(props) {
    super(props);
    this.state = {
      productdatail: this.props.productdetailProps
    };
  }

nó sẽ không hoạt động nếu bạn đặt phương thức side thành phầnDidMount () thông qua các đạo cụ.



2

bạn có thể sử dụng keygiá trị để đặt lại trạng thái khi cần, chuyển các đạo cụ để nói rằng đó không phải là một cách thực hành tốt, bởi vì bạn có thành phần không được kiểm soát và kiểm soát ở một nơi. Dữ liệu nên được xử lý ở một nơi, hãy đọc https://reactjs.org/blog/2018/06/07/you-probossible-dont-need-derured-state.html#recommendation-fully-uncontrolled-component-with-a -Chìa khóa


1

Bạn có thể sử dụng thành phầnWillReceiveProps.

constructor(props) {
    super(props);
    this.state = {
      productdatail: ''
    };
  }

    componentWillReceiveProps(nextProps){
        this.setState({ productdatail: nextProps.productdetailProps })
    }


1

BẠN PHẢI CẨN THẬN khi bạn khởi tạo statetừ propstrong constructor. Ngay cả khi propsthay đổi thành trạng thái mới, trạng thái sẽ không bị thay đổi vì việc gắn kết không bao giờ xảy ra nữa. Vì vậy, getDerivedStateFromPropstồn tại cho điều đó.

class FirstComponent extends React.Component {
    state = {
        description: ""
    };

    static getDerivedStateFromProps(nextProps, prevState) {
        if (prevState.description !== nextProps.description) {
          return { description: nextProps.description };
        }

        return null;
    }

    render() {
        const {state: {description}} = this;    

        return (
            <input type="text" value={description} /> 
        );
    }
}
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.