소품에서 구성 요소 초기화 상태를 반응


204

React 에서이 두 구현 사이에 실제 차이점이 있습니까? 어떤 친구들은 FirstComponent가 패턴이라고 말하지만 그 이유는 모르겠습니다. 렌더링이 한 번만 호출되므로 SecondComponent가 더 단순 해 보입니다.

먼저:

import React, { PropTypes } from 'react'

class FirstComponent extends React.Component {

  state = {
    description: ''
  }

  componentDidMount() {
    const { description} = this.props;
    this.setState({ description });
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} /> 
    );
  }
}

export default FirstComponent;

둘째:

import React, { PropTypes } from 'react'

class SecondComponent extends React.Component {

  state = {
    description: ''
  }

  constructor (props) => {
    const { description } = props;
    this.state = {description};
  }

  render () {
    const {state: { description }} = this;    
    return (
      <input type="text" value={description} />   
    );
  }
}

export default SecondComponent;

업데이트 : setState ()를 this.state = {} (감사합니다)로 변경했지만 여전히 차이가 보이지 않습니다. 하나가 다른 것보다 낫습니까?


10
소품을 왜 주에 보관하고 있습니까? 값을 캐싱하는 대신 소품을 직접 사용해야합니다. React.js에서 소품을 상태로 설정 하는 이유왜 신성 모독 이며 getInitialState의 소품은 안티 패턴 입니다.
Aurora0001

12
예-전환 가능한 구성 요소 (예 : 팝 오버 또는 서랍) 부모는 구성 요소를 열거 나 닫을 지 여부를 알고 있습니다. 구성 요소 자체는 특정 시점에 열려 있는지 여부를 알 수 있습니다. 그런 경우에는 this.state = { isVisible: props.isVisible }말이됩니다. 앱이 UI 상태를 배포하는 방법에 따라 다릅니다.
joews 2016 년


5
2017 년 Facebook은 propjs
Rohmer

1
@ Aurora0001 양식을 처리해야하는 상황에서 네트워크 요청을 자체적으로 작성하지만 해당 구성 요소에 대한 소품으로 제공되는 값으로 입력을 초기화해야하는 편집 양식을 말합니다. 양식을 동적으로 유지하려면 해당 값을 상태로 유지해야합니다.
Eric McWinNEr

답변:


196

상태로 변경되지 않는 속성을 복사하는 것은 안티 패턴입니다 (이 경우 .props에 직접 액세스). 결국 변경되지만 .props의 값으로 시작하는 상태 변수가있는 경우 생성자 호출조차 필요하지 않습니다.이 로컬 변수는 부모의 생성자에 대한 호출 후에 초기화됩니다.

class FirstComponent extends React.Component {
  state = {
    x: this.props.initialX,
    // You can even call functions and class methods:
    y: this.someMethod(this.props.initialY),
  };
}

이것은 아래 @joews의 답변에 해당하는 속기입니다. 최신 버전의 es6 트랜스 파일러에서만 작동하는 것 같습니다. 일부 웹팩 설정에서 문제가 있습니다. 그래도 문제가 해결되지 않으면 babel plugin 추가를 시도 babel-plugin-transform-class-properties하거나 아래 @joews에서 비 속기 버전을 사용할 수 있습니다.


1
답변이 @joews 답변과 어떻게 다른지 더 자세히 설명해 주시겠습니까?
Jalal

3
"변수를 설정하기 만하면 생성자 호출을 건너 뛸 수 있습니다."
Zane Hooper

3
작동하지 않으면이 babel 플러그인 "babel-plugin-transform-class-properties"를 설치해야합니다.
Faheem

2
상태가 초기화 후 소품에 의존하지 않는 것으로 이해되면 소품에서 상태를 초기화하는 것은 안티 패턴 이 아닙니다. 당신이이 동기화 유지하려는 경우, 그건 안티 패턴.
Yatrix

1
@ ak85 동일한 구문이지만 this.state를 대신 사용합니다. 이 문법은 클래스 구성 과정에서 상태를 설정하기위한 간단한 문법 일뿐입니다 (상태 이외의 변수에도 사용될 수 있음)
Zane Hooper

137

setState컴포넌트 를 호출 할 필요가 없습니다 . 직접 constructor설정하는 것은 관용적입니다 this.state.

class FirstComponent extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      x: props.initialX
    };
  }
  // ...
}

React 문서-클래스에 로컬 상태 추가를 참조하십시오 .

설명하는 첫 번째 방법에는 이점이 없습니다. 구성 요소를 처음으로 마운트하기 직전에 두 번째 업데이트가 발생합니다.


4
좋은 대답입니다. 이것은 초기 상태를 설정하기위한 것일뿐입니다. setState다른 지점에서 변경 한 경우 에도 여전히 사용해야 합니다. 그렇지 않으면 변경 사항이 렌더링되지 않을 수 있습니다.
Aurora0001

덕분에 다시 두 번째 문서 jowes facebook.github.io/react/docs/...을
레비 모레이라에게

(미안하지만 enter를 누르십시오.) 좀 더 복잡한 작업에서 getInitialState를 사용하여 소품을 상태로 설정해야합니다. 간단한 경우 this.props를 렌더링에 사용할 수 있습니까?
Levy Moreira

1
한계 참고 사항 : super(props)생성자에서 사용 하십시오. SO에 관한 토론
cutemachine

2
대부분의 경우 joews의 제안이 작동하지만 소품을 this.state에 직접 보내는 것에주의하십시오. props를 this.state에 복사하는 것은 실제로 단일 진실 소스 ( medium.com/react-ecosystem/… )가 아닙니다 . 또한 Dan Abramov는 소품 값을 상태에 저장하지 말 것을 제안했습니다. ( twitter.com/dan_abramov/status/749710501916139520/photo/1 ).
히로키

33

React 16.3 alpha에 대한 업데이트가 도입되었습니다 static getDerivedStateFromProps(nextProps, prevState)( 문서 ) componentWillReceiveProps.

getDerivedStateFromProps는 컴포넌트가 인스턴스화되고 새 소품을 수신 한 후에 호출됩니다. 객체를 업데이트 상태로 반환하거나 새 소품에 상태 업데이트가 필요하지 않음을 나타내려면 null을 반환해야합니다.

부모 구성 요소로 인해 구성 요소가 다시 렌더링되는 경우 소품이 변경되지 않은 경우에도이 메서드가 호출됩니다. 변경 사항 만 처리하려는 경우 새 값과 이전 값을 비교할 수 있습니다.

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

따라서이에 직접 액세스 할 수없는, 정적 this(그러나 그것은에 대한 액세스 권한을 가지고있다가 prevState, 보통에 부착 된 것을 저장할 수있는 this예를 refs)

댓글에 @nerfologist의 수정 사항을 반영하도록 편집


3
그냥 명확하게, 그것은라는 것 getDerivedStateFromProps(소품에서 대문자로 표시)과 PARAMS는 nextProps, prevState(하지 nextState) : reactjs.org/docs/...
nerfologist

1
와! 업데이트 된 소품 을받을 때 상태를 업데이트하기 위해 이것을 사용할 수 있습니다 !
Aromal Sasidharan

2
우리 getDerivedStateFromProps는 항상 초기 렌더링 전에 호출 되는 것을 고려하여 생성자에서 초기 상태를 만들어야 합니까?
bvdb

19

모든 소품을 상태에 추가하고 동일한 이름을 유지하려면 아래처럼 짧은 형식을 사용할 수 있습니다.

constructor(props) {
    super(props);
    this.state = {
       ...props
    }
    //...
}

1
상태로 변경되지 않는 속성을 복사하는 것은 안티 패턴입니다. 컴포넌트가 사용하는 필드를 명시 적으로 설명하는 것이 좋습니다.
Michael Freidgeim

5

생성자 내부의 상태 데이터를 다음과 같이 설정하십시오.

constructor(props) {
    super(props);
    this.state = {
      productdatail: this.props.productdetailProps
    };
  }

props를 통해 componentDidMount () 메소드 측에 설정하면 작동하지 않습니다.




1

componentWillReceiveProps를 사용할 수 있습니다.

constructor(props) {
    super(props);
    this.state = {
      productdatail: ''
    };
  }

    componentWillReceiveProps(nextProps){
        this.setState({ productdatail: nextProps.productdetailProps })
    }

1
componentWillReceiveProps는 향후 제공되지 않을 예정입니다
Vivek Ghanchi

1

생성자 state에서 초기화 할 때 조심해야합니다 props. props새로운 것으로 변경 하더라도 마운트가 다시 발생하지 않기 때문에 상태가 변경되지 않습니다. 그래서 getDerivedStateFromProps존재합니다.

class FirstComponent extends React.Component {
    state = {
        description: ""
    };

    static getDerivedStateFromProps(nextProps, prevState) {
        if (prevState.description !== nextProps.description) {
          return { description: nextProps.description };
        }

        return null;
    }

    render() {
        const {state: {description}} = this;    

        return (
            <input type="text" value={description} /> 
        );
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.