Чи можу я оновити реквізити компонента в React.js?


217

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

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

Це , здається, має на увазі , що властивості можуть змінитися на компоненті на основі порівняння nextPropsз this.props. Що я пропускаю? Як змінюються реквізити, або я помиляюся про те, куди це викликається?

Відповіді:


249

Компонент не може оновлювати свої власні реквізити, якщо вони не є масивами або об'єктами (наявність компонента оновлення власних реквізитів, навіть якщо це можливо, є анти-шаблоном), але може оновити свій стан та реквізити своїх дітей.

Наприклад, приладова панель має speedполе у ​​своєму стані та передає її дочірнім вимірювачем, який відображає цю швидкість. Його renderметод справедливий return <Gauge speed={this.state.speed} />. Коли викличе інформаційна панель this.setState({speed: this.state.speed + 1}), вимірювальний пристрій повторно відображається з новим значенням для speed.

Незадовго до того, як це станеться, componentWillReceivePropsвикликається датчик вимірювальних знаків , щоб датчик міг порівняти нове значення зі старим.


Тож звучить так, що його викликають один раз, коли компонент React ініціалізується та отримує реквізит. Реквізит насправді не «змінюється», коли компонент створений. Це так?
Метт Хаггінс

12
Протилежність. Документація каже: «Викликається , коли компонент отримує новий реквізит Цей метод не викликається для початкового рендеринга ..»
Валері

Дякую. Це запитання виникла з початкового непорозуміння React у тому, що компонент буде повторно використаний при повторному відображенні екрана (або його частини).
Метт Хаггінс

1
Так. Компонент може прослуховувати подію та оновлювати її стан щоразу, коли подія запускається.
Valéry

8
Я приходжу з майбутнього: componentWillReceivePropsзастарів зараз: і замінений комбінацією getDerivedStateFromPropsі componentDidUpdate.
bvdb

53

ЗАПИТИ

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

ДЕРЖАВ

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

Хороший приклад вже надає Валері.


4
@ali_adravi - це цитати, кудись скопійовані? Якщо так, то яка довідка? Або це ваші слова, і ви просто відформатували їх як цитати наголосів?
Роб Беднарк

@RobBednark зараз не пам’ятаю точного джерела, але впевнений, що це правдиве твердження з невеликою модифікацією речення з якоїсь книги.
Алі Адраві

26

Реквізити можуть змінюватися, коли батьківський компонент знову надає компонент з різними властивостями. Я думаю, що це в основному оптимізація, так що жоден новий компонент не потребує прискорення.


3

Намагайтеся оновити реквізити, якщо вони є масивом:

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
Я думаю, що стан ініціалізації за допомогою реквізиту є анти-шаблоном, його слід уникати. ось хороше посилання, щоб прочитати github.com/vasanthk/react-bits/blob/master/anti-patterns/… .
tryHendri


0

якщо ви використовуєте 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);

наведіть приклад
vsync
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.