componentWillReceiveProps와 달리 라이프 사이클 메소드 getDerivedStateFromProps를 사용하는 방법


142

마치 componentWillReceiveProps완전히 새로운 라이프 사이클 방식에 찬성, 오는 릴리스에서 단계적으로 될 것입니다 getDerivedStateFromProps: 정적 getDerivedStateFromProps를 () .

검사 한 결과 this.propsnextProps에서 직접 님과 직접 비교할 수없는 것 같습니다 componentWillReceiveProps. 이 주위에 어떤 방법이 있습니까?

또한 이제 객체를 반환합니다. 반환 값이 본질적으로 있다고 가정하는 것이 맞 this.setState습니까?

아래는 온라인에서 찾은 예 입니다. States props / state에서 파생되었습니다 .

전에

class ExampleComponent extends React.Component {
  state = {
    derivedData: computeDerivedState(this.props)
  };

  componentWillReceiveProps(nextProps) {
    if (this.props.someValue !== nextProps.someValue) {
      this.setState({
        derivedData: computeDerivedState(nextProps)
      });
    }
  }
}

class ExampleComponent extends React.Component {
  // Initialize state in constructor,
  // Or with a property initializer.
  state = {};

  static getDerivedStateFromProps(nextProps, prevState) {
    if (prevState.someMirroredValue !== nextProps.someValue) {
      return {
        derivedData: computeDerivedState(nextProps),
        someMirroredValue: nextProps.someValue
      };
    }

    // Return null to indicate no change to state.
    return null;
  }
}

답변:


96

제거 정보 componentWillReceiveProps: getDerivedStateFromProps및 의 조합으로 사용을 처리 할 수 ​​있어야 합니다. 마이그레이션 예 는 React 블로그 게시물componentDidUpdate참조하십시오 . 그리고 네에 의해 반환 된 객체는에 전달 된 객체와 유사하게 상태 를 업데이트합니다 .getDerivedStateFromPropssetState

소품의 오래된 가치가 정말로 필요한 경우 항상 다음과 같은 상태로 소품을 캐시 할 수 있습니다.

state = {
  cachedSomeProp: null
  // ... rest of initial state
};

static getDerivedStateFromProps(nextProps, prevState) {
  // do things with nextProps.someProp and prevState.cachedSomeProp
  return {
    cachedSomeProp: nextProps.someProp,
    // ... other derived state properties
  };
}

상태에 영향을주지 않습니다 아무것도에 넣어 수 있습니다 componentDidUpdate, 심지어 거기에 getSnapshotBeforeUpdate매우 낮은 수준의 물건.

업데이트 : 새로운 (그리고 오래된) 라이프 사이클 방법에 대한 느낌을 얻으려면 react-lifecycle-visualizer 패키지가 도움이 될 수 있습니다.


1
어, 나는 질문을 엉망으로 만들었다. 나는 실제로 의미했다componentWillReceiveProps
Andrew

2
이전 소품을 보유하기 위해 내 상태를 사용하려고 생각했지만 실제로 구현하는 데 필요한 추가 코드와 논리를 피하고 싶었습니다. 나는 당신이 제기하는 다른 것들을 살펴볼 것입니다. 많은 감사합니다!
Andrew

4
이전 소품을 상태로 저장해야하는 것은 이해하기 어려운이 React API 변경에 대한 간단한 해결책입니다. 많은 개발자의 눈에는 반 패턴과 회귀 변화처럼 보입니다. Oblosys를 비판하지는 않지만 React 팀.
AxeEffect

2
@AxeEffect 이것은 getDerivedStateFromProps실제로 메모를위한 것이 아니기 때문 입니다. 대신 권장 접근법을 설명 아래의 답변을 참조하십시오 .
Dan Abramov

오타입니까? 보고 싶었어 ...? 즉, 전체 상태 객체 또는 관심있는 부분 만 반환해야합니다.
프로그래머

51

우리는 다음과 같이 최근에 게시 된 블로그 반응 , 대부분의 경우에 필요하지 않은 getDerivedStateFromProps전혀 .

일부 파생 데이터 만 계산하려면 다음 중 하나를 수행하십시오.

  1. 바로 해봐 render
  2. 또는 다시 계산하는 데 비용이 많이 드는 경우와 같은 메모 도우미를 사용하십시오 memoize-one.

가장 간단한 "후"예는 다음과 같습니다.

import memoize from "memoize-one";

class ExampleComponent extends React.Component {
  getDerivedData = memoize(computeDerivedState);

  render() {
    const derivedData = this.getDerivedData(this.props.someValue);
    // ...
  }
}

자세한 내용 은 블로그 게시물의이 섹션을 확인하십시오 .


45
그것이 필요하지 않다면 광대 의 경우 대부분, 나는이 같은 몹시 필요로 변화했다 작업 프로젝트의 수천을 깰 것 하나를 놀라게하고있다. React 팀이 엔지니어링을 시작한 것 같습니다.
Ska

39
componentWillReceiveProps에서 getDerivedStateFromProps로 변경하십시오. 기존 코드를 모두 리팩토링하는 것은 깨지지 않고 시간이 많이 걸리는 일입니다. 그리고 대부분의 경우에 그것을 사용해서는 안된다고 말했기 때문에 이점이 거의없는 것 같습니다. 왜 처음부터 사용해서는 안되는 API를 변경해야하는 번거 로움을 겪어야 하는가?
Ska

4
Dan Abramov의 의견에 대한 답변을 듣고 싶습니다.
Louis345

6
@DanAbramov이 변경이 왜 발생했는지에 대한 답변이 있습니까?
Petros Kyriakou

3
실제로 우리 프로젝트에서 이것은 많이 사용됩니다. 예를 들어 새로운 데이터가 다운 될 때 화면에 스낵바와 같은 것을 표시합니다. componentWillReceiveProps간단하고 작동했습니다. 이 정적 쓰레기를 위해 그것을 제거
Oliver Dixon

6

Dan Abramov가 언급했듯이

렌더링 내에서 바로 수행

우리는 실제로 그 계산 방식을 상태 계산에 대한 모든 종류의 프록 싱 소품에 대해 메모와 함께 사용합니다.

우리의 코드는 이런 식으로 보인다

// ./decorators/memoized.js  
import memoizeOne from 'memoize-one';

export function memoized(target, key, descriptor) {
  descriptor.value = memoizeOne(descriptor.value);
  return descriptor;
}

// ./components/exampleComponent.js
import React from 'react';
import { memoized } from 'src/decorators';

class ExampleComponent extends React.Component {
  buildValuesFromProps() {
    const {
      watchedProp1,
      watchedProp2,
      watchedProp3,
      watchedProp4,
      watchedProp5,
    } = this.props
    return {
      value1: buildValue1(watchedProp1, watchedProp2),
      value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
      value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
    }
  }

  @memoized
  buildValue1(watchedProp1, watchedProp2) {
    return ...;
  }

  @memoized
  buildValue2(watchedProp1, watchedProp3, watchedProp5) {
    return ...;
  }

  @memoized
  buildValue3(watchedProp3, watchedProp4, watchedProp5) {
    return ...;
  }

  render() {
    const {
      value1,
      value2,
      value3
    } = this.buildValuesFromProps();

    return (
      <div>
        <Component1 value={value1}>
        <Component2 value={value2}>
        <Component3 value={value3}>
      </div>
    );
  }
}

그것의 이점은 비교 보일러 내부의 코드 톤이 필요하지 않는 것이 있습니다 getDerivedStateFromProps또는 componentWillReceiveProps당신이 생성자 내부 초기화 복사 - 붙여 넣기 건너 뛸 수 있습니다.

노트:

이 접근 방식은 소품을 상태로 프록시하는 데만 사용됩니다. 내부 상태 논리가있는 경우 여전히 구성 요소 수명주기에서 처리해야합니다.

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