Tôi có thể cập nhật đạo cụ của một thành phần trong React.js không?


217

Sau khi bắt đầu làm việc với React.js, có vẻ như propsđược dự định là tĩnh (được truyền từ thành phần chính), trong khi statethay đổi dựa trên các sự kiện. Tuy nhiên, tôi nhận thấy trong các tài liệu tham chiếu đến componentWillReceiveProps, trong đó bao gồm cụ thể ví dụ này:

componentWillReceiveProps: function(nextProps) {
  this.setState({
    likesIncreasing: nextProps.likeCount > this.props.likeCount
  });
}

Điều này dường như ngụ ý rằng các thuộc tính CÓ THỂ thay đổi trên một thành phần dựa trên việc so sánh nextPropsvới this.props. Tôi đang thiếu gì? Làm thế nào để thay đổi đạo cụ, hoặc tôi nhầm về nơi này được gọi là gì?

Câu trả lời:


249

Một thành phần không thể cập nhật đạo cụ riêng của mình trừ khi chúng là mảng hoặc đối tượng (có thành phần cập nhật đạo cụ riêng ngay cả khi có thể là chống mẫu), nhưng có thể cập nhật trạng thái và đạo cụ của trẻ em.

Chẳng hạn, Bảng điều khiển có một speedtrường ở trạng thái của nó và chuyển nó cho một máy đo con hiển thị tốc độ này. renderPhương pháp của nó chỉ là return <Gauge speed={this.state.speed} />. Khi Bảng điều khiển gọi this.setState({speed: this.state.speed + 1}), Máy đo được kết xuất lại với giá trị mới cho speed.

Ngay trước khi điều này xảy ra, Máy đo componentWillReceivePropsđược gọi, để Máy đo có cơ hội so sánh giá trị mới với giá trị cũ.


Vì vậy, có vẻ như nó được gọi một lần khi thành phần React được khởi tạo và đang nhận đạo cụ. Các đạo cụ không thực sự "thay đổi" khi một thành phần được tạo. Có đúng không?
Matt Huggins

12
Mặt đối diện, sự đối nghịch. Các tài liệu cho biết: "Viện dẫn khi một thành phần được nhận đạo cụ mới phương pháp này không được kêu gọi ban đầu render.."
Valéry

Cảm ơn. Câu hỏi này xuất phát từ sự hiểu lầm ban đầu về React ở chỗ một thành phần sẽ được sử dụng lại khi đăng ký lại màn hình (hoặc một phần của màn hình).
Matt Huggins

1
Đúng. Một thành phần có thể nghe một sự kiện và cập nhật trạng thái của nó mỗi khi sự kiện này kích hoạt.
Valéry

8
Tôi đến từ tương lai: componentWillReceivePropsđã lỗi thời: và được thay thế bằng sự kết hợp của getDerivedStateFromPropscomponentDidUpdate.
bvdb

53

DỰ ÁN

Thành phần React nên sử dụng đạo cụ để lưu trữ thông tin có thể thay đổi, nhưng chỉ có thể được thay đổi bởi một thành phần khác.

TIỂU BANG

Một thành phần React nên sử dụng trạng thái để lưu trữ thông tin mà chính thành phần đó có thể thay đổi.

Một ví dụ tốt đã được cung cấp bởi Valéry.


4
@ali_adravi là những trích dẫn được sao chép từ đâu đó? Nếu vậy, tài liệu tham khảo là gì? Hoặc đó là những từ của bạn, và bạn chỉ định dạng chúng là trích dẫn để nhấn mạnh?
Rob Bednark

@RobBednark Bây giờ tôi không nhớ nguồn chính xác, nhưng chắc chắn đó là tuyên bố đúng với một chút sửa đổi trong câu từ một số cuốn sách.
Ali Adravi

26

Đạo cụ có thể thay đổi khi cha mẹ của thành phần kết xuất lại thành phần đó với các thuộc tính khác nhau. Tôi nghĩ rằng đây chủ yếu là một tối ưu hóa để không cần phải khởi tạo thành phần mới.


3

Thủ thuật để cập nhật đạo cụ nếu chúng là mảng:

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Button
} from 'react-native';

class Counter extends Component {
  constructor(props) {
    super(props);
      this.state = {
        count: this.props.count
      }
    }
  increment(){
    console.log("this.props.count");
    console.log(this.props.count);
    let count = this.state.count
    count.push("new element");
    this.setState({ count: count})
  }
  render() {

    return (
      <View style={styles.container}>
        <Text>{ this.state.count.length }</Text>
        <Button
          onPress={this.increment.bind(this)}
          title={ "Increase" }
        />
      </View>
    );
  }
}

Counter.defaultProps = {
 count: []
}

export default Counter
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

3
Tôi nghĩ rằng khởi tạo trạng thái với các đạo cụ là chống mẫu, nên tránh. đây là đường dẫn tốt để đọc github.com/vasanthk/react-bits/blob/master/anti-potypes/iêu .
thửHendri


0

nếu bạn sử dụng recompose, sử dụng mapPropsđể tạo đạo cụ mới có nguồn gốc từ đạo cụ đến

Chỉnh sửa ví dụ:

import { compose, mapProps } from 'recompose';

const SomeComponent = ({ url, onComplete }) => (
  {url ? (
    <View />
  ) : null}
)

export default compose(
  mapProps(({ url, storeUrl, history, ...props }) => ({
    ...props,
    onClose: () => {
      history.goBack();
    },
    url: url || storeUrl,
  })),
)(SomeComponent);

vui lòng cung cấp một ví dụ
vsync
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.