[reactjs] 반응 양식의 소품 변경 상태 업데이트

React 양식에 문제가 있고 상태를 올바르게 관리하고 있습니다. 양식에 모달로 된 시간 입력 필드가 있습니다. 초기 값은의 상태 변수로 설정되며 getInitialState상위 구성 요소에서 전달됩니다. 이것은 그 자체로 잘 작동합니다.

부모 구성 요소를 통해 기본 start_time 값을 업데이트하려고 할 때 문제가 발생합니다. 업데이트 자체는를 통해 상위 구성 요소에서 발생합니다 setState start_time: new_time. 그러나 내 양식에서 기본 start_time 값은에 한 번만 정의되므로 변경되지 않습니다 getInitialState.

componentWillUpdate통해 상태를 강제로 변경 하려고 시도했지만 setState start_time: next_props.start_time실제로 작동했지만 Uncaught RangeError: Maximum call stack size exceeded오류가 발생했습니다.

내 질문은,이 경우 상태를 업데이트하는 올바른 방법은 무엇입니까? 어떻게 든이 잘못에 대해 생각하고 있습니까?

현재 코드 :

@ModalBody = React.createClass
  getInitialState: ->
    start_time: @props.start_time.format("HH:mm")

  #works but takes long and causes:
  #"Uncaught RangeError: Maximum call stack size exceeded"
  componentWillUpdate: (next_props, next_state) ->
    @setState(start_time: next_props.start_time.format("HH:mm"))

  fieldChanged: (fieldName, event) ->
    stateUpdate = {}
    stateUpdate[fieldName] = event.target.value
    @setState(stateUpdate)

  render: ->
    React.DOM.div
      className: "modal-body"
      React.DOM.form null,
        React.createElement FormLabelInputField,
          type: "time"
          id: "start_time"
          label_name: "Start Time"
          value: @state.start_time
          onChange: @fieldChanged.bind(null, "start_time”)

@FormLabelInputField = React.createClass
  render: ->
    React.DOM.div
      className: "form-group"
      React.DOM.label
        htmlFor: @props.id
        @props.label_name + ": "
      React.DOM.input
        className: "form-control"
        type: @props.type
        id: @props.id
        value: @props.value
        onChange: @props.onChange



답변

반응식 16 이후 componentWillReceiveProps는 depcricated입니다 . 대신 getDerivedStateFromProps 를 사용하십시오 .

올바르게 이해하면 상위 구성 요소로 전달되는 상위 구성 요소가 있습니다 start_time.ModalBody 자신의 상태에 할당 구성 요소로 있습니까? 그리고 하위 구성 요소가 아닌 상위에서 해당 시간을 업데이트하려고합니다.

React에는이 시나리오를 다루는 데 유용한 정보가 있습니다. (이 기사는 웹에서 삭제 된 이전 기사입니다. 컴포넌트 props에 대한 현재 문서에 대한 링크가 있습니다.)

소품을 사용하여 상태를 생성하는 것은 getInitialState종종 “진실의 근원”, 즉 실제 데이터가있는 곳의 복제로 이어집니다. 이 때문입니다getInitialState구성 요소를 처음 작성할 때만 호출 입니다.

가능할 때마다 값을 즉시 계산하여 나중에 동기화되지 않고 유지 보수 문제를 유발하지 않도록하십시오.

기본적으로 부모 props를 자식 에게 할당 할 때마다 stateprop 업데이트시 render 메서드가 항상 호출되는 것은 아닙니다. componentWillReceiveProps메소드를 사용하여 수동으로 호출해야합니다 .

componentWillReceiveProps(nextProps) {
  // You don't have to do this check first, but it can help prevent an unneeded render
  if (nextProps.startTime !== this.state.startTime) {
    this.setState({ startTime: nextProps.startTime });
  }
}


답변

분명히 상황이 바뀌고 있습니다 … getDerivedStateFromProps () 가 이제 선호되는 기능입니다.

class Component extends React.Component {
  static getDerivedStateFromProps(props, current_state) {
    if (current_state.value !== props.value) {
      return {
        value: props.value,
        computed_prop: heavy_computation(props.value)
      }
    }
    return null
  }
}

(danburzo @ github 코드 위)


답변

componentWillReceiveProps “종종 버그와 불일치가 발생하기 때문에”더 이상 사용되지 않습니다.

외부에서 무언가가 바뀌면으로 하위 구성 요소를 완전히 재설정하는 것이key 좋습니다.

key자식 구성 요소에 소품을 제공 key하면 외부 의 값이 변경 될 때마다이 구성 요소가 다시 렌더링됩니다. 예 :

<EmailInput
  defaultEmail={this.props.user.email}
  key={this.props.user.id}
/>

성능상 :

느리게 들릴 수 있지만 일반적으로 성능 차이는 중요하지 않습니다. 하위 트리에 대해 diffing이 무시되므로 구성 요소에 업데이트시 실행되는 논리가 많은 경우 키를 사용하는 것이 더 빠를 수도 있습니다.


답변

도 있습니다 componentDidUpdate 이 없습니다.

기능 signatur :

componentDidUpdate(prevProps, prevState, snapshot)

컴포넌트가 업데이트 될 때 DOM에서 작동 할 수있는 기회로 이것을 사용하십시오. initial에 호출되지 않습니다 render.

보기 당신은 아마 국가 파생하지 않아도 모두 안티 패턴을 설명 제, componentDidUpdategetDerivedStateFromProps. 나는 그것이 매우 유용하다는 것을 알았습니다.


답변

이 작업을 수행하는 새로운 후크 방법은 componentWillReceiveProps 대신 useEffect를 사용하는 것입니다.

componentWillReceiveProps(nextProps) {
  // You don't have to do this check first, but it can help prevent an unneeded render
  if (nextProps.startTime !== this.state.startTime) {
    this.setState({ startTime: nextProps.startTime });
  }
}

기능 후크 구동 구성 요소에서 다음이됩니다.

// store the startTime prop in local state
const [startTime, setStartTime] = useState(props.startTime)
// 
useEffect(() => {
  if (props.startTime !== startTime) {
    setStartTime(props.startTime);
  }
}, [props.startTime]);

setState를 사용하여 상태를 설정하고 useEffect를 사용하여 지정된 소품에 대한 변경 사항을 확인하고 소품 변경시 상태를 업데이트하는 조치를 취합니다.


답변

당신은 아마 파생 국가가 필요하지 않습니다

1. 부모로부터 키를 설정

키가 변경되면 React는 현재 인스턴스를 업데이트하지 않고 새 컴포넌트 인스턴스를 만듭니다. 키는 일반적으로 동적 목록에 사용되지만 여기서도 유용합니다.

2. getDerivedStateFromProps/ 사용componentWillReceiveProps

어떤 이유로 키가 작동하지 않는 경우 (아마도 구성 요소가 초기화하는 데 너무 비쌉니다)

를 사용 getDerivedStateFromProps하면 상태의 일부를 재설정 할 수 있지만 현재 약간 버그가 있습니다 (v16.7) ! , 사용법에 대해서는 위의 링크를 참조하십시오


답변

반응 문서에서 : https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

소품 변경시 소거 상태가 안티 패턴

React 16부터 componentWillReceiveProps는 더 이상 사용되지 않습니다. 반응 문서 에서이 경우 권장되는 접근 방식은 사용입니다.

  1. 완전 구성 요소 제어 다음 ParentComponent의가 ModalBody자신의 것입니다 start_time상태. 이것은 모달 이이 상태를 소유해야한다고 생각하기 때문에이 경우에는 선호하는 접근법이 아닙니다.
  2. 키가있는 완전히 제어되지 않은 구성 요소 : 이것은 내가 선호하는 접근법입니다. :의 예는 문서 반응 https://codesandbox.io/s/6v1znlxyxn를 . 당신은 당신의 start_time상태를 완전히 소유하고 이미했던 것처럼 ModalBody사용 getInitialState합니다. start_time상태 를 재설정하려면 간단히ParentComponent