Могу ли я обновить компонентные реквизиты в React.js?

После начала работы с React.js, похоже, что props предполагается статическим (передается из родительского компонента), а state изменяется в зависимости от событий. Тем не менее, я заметил в документах ссылку на componentWillReceiveProps, которая включает в себя этот пример:

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

Это, по-видимому, означает, что свойства CAN могут меняться на компоненте, основанном на сравнении nextProps - this.props. Что мне не хватает? Как изменяются реквизит, или я ошибаюсь в том, где это называется?

Ответ 1

Компонент не может обновлять свои собственные реквизиты, если они не являются массивами или объектами (с обновлением компонента его собственных реквизитов, даже если это возможно, является анти-шаблоном), но может обновлять его состояние и реквизиты своих дочерних элементов.

Например, панель управления имеет поле speed в своем состоянии и передает ее дочернему элементу Gauge, который отображает эту скорость. Его метод render равен return <Gauge speed={this.state.speed} />. Когда Dashboard вызывает this.setState({speed: this.state.speed + 1}), калибровка перерисовывается с новым значением для speed.

Прежде чем это произойдет, вызывается Gauge componentWillReceiveProps, так что Калибровка имеет возможность сравнить новое значение со старым.

Ответ 2

PROPS

Компонент React должен использовать реквизит для хранения информации, которая может быть изменен, но может быть изменен только другим компонентом.

ГОСУДАРСТВЕННЫЕ

Компонент React должен использовать состояние для хранения информации, которую сам компонент может измениться.

Хороший пример уже предоставлен Валери.

Ответ 3

Реквизиты могут меняться, когда родитель компонента снова отображает компонент с различными свойствами. Я думаю, что это в основном оптимизация, так что новый компонент не должен быть создан.

Ответ 4

Хитрость для обновления реквизита, если он является массивом:

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

Ответ 5

если вы используете recompose, используйте mapProps для создания новых реквизитов, полученных из входящих реквизитов

Изменить, например:

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