Czy mogę zaktualizować rekwizyty komponentu w React.js?


217

Po rozpoczęciu pracy z React.js wygląda na to, że propsmają być statyczne (przekazywane z komponentu nadrzędnego), a statezmiany oparte na zdarzeniach. Jednak zauważyłem w dokumentach odniesienie componentWillReceiveProps, które konkretnie obejmuje ten przykład:

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

To zdaje się sugerować, że właściwości można zmienić na komponencie w oparciu o porównania nextPropsdo this.props. czego mi brakuje? Jak zmieniają się rekwizyty, czy też mylę się co do tego, jak to się nazywa?

Odpowiedzi:


249

Składnik nie może aktualizować własnych rekwizytów, chyba że są to tablice lub obiekty (posiadanie składnika aktualizującego własne rekwizyty, nawet jeśli jest to możliwe, jest anty-wzorcem), ale może aktualizować swój stan i rekwizyty swoich potomków.

Na przykład pulpit nawigacyjny ma speedpole w swoim stanie i przekazuje je do potomka miernika, który wyświetla tę prędkość. Jego rendermetoda jest sprawiedliwa return <Gauge speed={this.state.speed} />. Gdy panel kontrolny wywołuje this.setState({speed: this.state.speed + 1}), miernik jest renderowany ponownie z nową wartością dla speed.

Tuż przed tym zdarza componentWillReceivePropssię wywoływanie miernika , aby miernik miał szansę porównać nową wartość ze starą.


Brzmi więc tak, jakby był wywoływany raz, gdy składnik React jest inicjowany i otrzymuje rekwizyty. Rekwizyty nie zmieniają się po utworzeniu komponentu. Czy to prawda?
Matt Huggins

12
Przeciwieństwo. Dokumentacja mówi: „wywoływana, gdy składnik odbiera nowe rekwizyty Metoda ta nie jest wymagana wstępna render.”.
Valéry

Dzięki. To pytanie wynikało z początkowego nieporozumienia React polegającego na tym, że komponent zostanie ponownie użyty podczas ponownego wysyłania ekranu (lub jego części).
Matt Huggins

1
Tak. Składnik może nasłuchiwać zdarzenia i aktualizować jego stan przy każdym uruchomieniu zdarzenia.
Valéry,

8
Pochodzę z przyszłości: componentWillReceivePropsjest już przestarzały: i zastąpiony przez kombinację getDerivedStateFromPropsi componentDidUpdate.
bvdb,

53

PROPS

Składnik React powinien używać rekwizytów do przechowywania informacji, które można zmienić, ale można je zmienić tylko za pomocą innego składnika.

STAN

Składnik React powinien używać stanu do przechowywania informacji, które sam składnik może zmienić.

Dobry przykład podał już Valéry.


4
@ali_adravi czy te cytaty są gdzieś kopiowane? Jeśli tak, jakie jest odniesienie? A może to są twoje słowa i właśnie sformatowałeś je jako cytaty dla podkreślenia?
Rob Bednark,

@RobBednark Nie pamiętam teraz dokładnego źródła, ale pewne jest to prawdziwe stwierdzenie z niewielką modyfikacją zdania z jakiejś książki.
Ali Adravi

26

Rekwizyty mogą się zmieniać, gdy element macierzysty komponentu ponownie renderuje komponent z różnymi właściwościami. Myślę, że jest to głównie optymalizacja, więc nie trzeba tworzyć instancji żadnego nowego komponentu.


3

Sztuczka, aby zaktualizować rekwizyty, jeśli są tablicami:

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
Myślę, że należy unikać inicjalizacji stanu za pomocą rekwizytów. tutaj jest dobry link do przeczytania github.com/vasanthk/react-bits/blob/master/anti-patterns/… .
tryHendri,


0

jeśli używasz recompose, użyj mapPropsdo tworzenia nowych rekwizytów pochodzących z przychodzących rekwizytów

Edytuj na przykład:

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

podaj przykład
vsync,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.