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 구성 요소가 초기화되고 소품을 수신 할 때 한 번 호출되는 것처럼 들립니다. 소품은 컴포넌트가 생성되면 실제로 "변경"되지 않습니다. 맞습니까?
Matt Huggins

12
반대. 문서는 말한다 : "호출이 구성 요소가 새로운 소품을 수신 할 때 초기 렌더링을 위해이 메소드가 호출되지 않습니다.."
발레리

감사. 이 질문은 화면 (또는 화면의 일부)을 다시 렌더링 할 때 구성 요소를 다시 사용할 것이라는 React의 초기 오해에서 비롯되었습니다.
매트 허긴 스

1
예. 구성 요소는 이벤트를 수신하고 이벤트가 발생할 때마다 상태를 업데이트 할 수 있습니다.
Valéry

8
나는 미래에서 온 : componentWillReceiveProps이제 구식이되어와의 조합으로 대체 getDerivedStateFromProps하고 componentDidUpdate.
bvdb

53

소품

React 컴포넌트는 props를 사용하여 변경할 수 있지만 다른 컴포넌트에 의해서만 변경 될 수있는 정보를 저장해야합니다.

상태

React 컴포넌트는 state 자체를 사용하여 컴포넌트 자체가 변경할 수있는 정보를 저장해야합니다.

좋은 예가 이미 Valéry에 의해 제공되었습니다.


4
@ali_adravi 그 따옴표는 어딘가에서 복사 되었습니까? 그렇다면 참조 란 무엇입니까? 아니면 당신의 단어가 있습니까?
Rob Bednark

@RobBednark 나는 정확한 출처를 기억하지 못하지만, 그것은 어떤 책의 문장을 약간 수정하여 진정한 진술이라고 확신합니다.
Ali Adravi

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.