web-dev-qa-db-ja.com

React.jsで対応の小道具を更新できますか?

React.jsを使い始めた後は、propsは静的(親コンポーネントから渡される)であることが意図されているようですが、stateはイベントに基づいて変更されます。しかし、私はdocsの中で componentWillReceiveProps への参照に気づいた。具体的にはこの例を含む:

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

これは、nextPropsthis.propsの比較に基づいて、コンポーネントのプロパティが変更される可能性があることを暗示しているようです。何が足りないの?小道具はどのように変化するのでしょうか、それとも私はこれが呼ばれる場所を間違えていますか?

163
Matt Huggins

コンポーネントは、それらが配列またはオブジェクトでない限り、独自のプロップを更新することはできません(可能であればコンポーネントに独自のプロップを更新させることはアンチパターンです)が、その状態とその子のプロップは更新できます。

たとえば、Dashboardはその状態にspeedフィールドを持ち、それをこの速度を表示するGaugeの子に渡します。そのrenderメソッドはちょうどreturn <Gauge speed={this.state.speed} />です。ダッシュボードがthis.setState({speed: this.state.speed + 1})を呼び出すと、Gaugeはspeedの新しい値で再レンダリングされます。

これが起こる直前に、GaugeのcomponentWillReceivePropsが呼び出されるので、Gaugeは新しい値を古い値と比較する機会があります。

201
Valéry

コンポーネントの親が異なるプロパティを使用してコンポーネントを再度レンダリングすると、小道具が変わることがあります。これは大部分が最適化であるため、新しいコンポーネントをインスタンス化する必要はありません。

22

PROPS

Reactコンポーネントは、変更可能な情報を格納するために小道具を使用するべきですが、別のコンポーネントによってのみ変更可能です。

状態

Reactコンポーネントはstateを使用して、コンポーネント自体が変更できるという情報を格納します。

良い例はすでにValéryによって提供されています。

20
Ali Adravi

それらが配列であるならば、小道具を更新するためのトリック:

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
      }
    }
  increament(){
    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.increament.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,
  },
});
2
Abhishek Kumar

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