itsource

반응 양식에서 소품 변경에 대한 상태

mycopycode 2023. 4. 2. 10:24
반응형

반응 양식에서 소품 변경에 대한 상태

리액트 폼과 상태 관리에 문제가 있습니다.양식(모달)에 시간 입력 필드가 있습니다.됩니다.getInitialState부모 컴포넌트에서 전달됩니다.이치노

이 문제는 부모 컴포넌트를 통해 기본 start_time 값을 갱신할 때 발생합니다.는 부모 에서 업업음음 음음음음음 음음음음음을 통해 합니다.setState start_time: new_time, 제 "Default "는 "Default" 입니다start_time은 단 한 입니다.getInitialState.

사용하려고 했습니다.componentWillUpdate setState start_time: next_props.start_time실제로 효과가 , 「실로 me me me me」를 주었다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

componentWillReceiveProps는 react 16으로 디컴퍼넌트화 되었습니다.대신 getDerivedStateFromProps를 사용합니다.

중에 컴포넌트가 있는 맞다면, 부모 컴포넌트에는 부모 컴포넌트가 있습니다.start_timeModalBody컴포넌트가 합니다.또한 하위 구성 요소가 아닌 상위 구성 요소에서 시간을 업데이트해야 합니다.

React에는 이 시나리오에 대처하기 위한 몇 가지 힌트가 있습니다.(이 문서는 그 후 웹에서 삭제된 오래된 문서입니다.컴포넌트 소품 관련 최신 문서에 대한 링크입니다.)

을 사용하여 를 발생시키다getInitialState종종 "진실의 원천" 즉, 실제 데이터가 있는 곳의 중복으로 이어집니다.그 이유는getInitialState컴포넌트가 처음 생성되었을 때만 호출됩니다.

가능한 한 값을 즉시 계산하여 나중에 동기화되지 않도록 하고 유지 보수 문제를 일으키지 않도록 하십시오.

으로는 부모의propsstate렌더 메서드가 항상 프로펠러 업데이트에서 호출되는 것은 아닙니다.요.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 });
  }
}

상황이 변하고 있는 것 같아...get Derived State From Props()는 현재 권장 함수입니다.

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
  }
}

(위 코드 by danburzo @ github)

componentWillReceiveProps를 사용하면 "흔히 버그나 불일치가 발생한다"는 이유로 권장되지 않습니다.

외부에서 뭔가 변경된 경우 컴포넌트 전체를 로 리셋하는 것을 검토해 주십시오.

의 제공key 프로포트를 하면 값이 됩니다.key들어,

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

퍼포먼스에 대해서:

느린 것처럼 들릴 수 있지만 성능 차이는 보통 미미합니다.하위 트리에 대해 확산이 무시되므로 컴포넌트가 업데이트 시 실행되는 무거운 논리를 가진 경우 키를 사용하는 것이 더 빠를 수 있습니다.

새로운 후크 방식은 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를 사용하여 지정된 프로포트의 변경을 확인하고 프로포트의 변경 시 상태를 갱신하는 액션을 수행합니다.

componentDidUpdate도 있습니다.

기능 시그니처:

componentDidUpdate(prevProps, prevState, snapshot)

컴포넌트가 갱신되었을 때, 이것을 DOM 의 조작의 기회로 사용합니다.render.

See You Umpted Needed Derived State 문서(양쪽 모두 안티패턴에 대해 설명)componentDidUpdate ★★★★★★★★★★★★★★★★★」getDerivedStateFromProps나는 그것이 매우 유용하다는 것을 알았다.

파생 상태가 필요 없는 경우가 많다

1. 부모로부터 키를 설정한다.

키가 변경되면 React는 현재 구성 요소 인스턴스를 업데이트하는 대신 새 구성 요소 인스턴스를 생성합니다.키는 일반적으로 동적 목록에 사용되지만 여기서도 유용합니다.

. 2. 용 2getDerivedStateFromPropscomponentWillReceiveProps

어떤 이유로 키가 작동하지 않는 경우(컴포넌트를 초기화하는데 비용이 많이 들 수 있음)

「」를 사용해 .getDerivedStateFromProps스테이트의 어느 부분을 리셋 할 수 있습니다만, 현시점에서는 조금 버그가 있는 것 같습니다(v16.7).사용방법에 대해서는 위의 링크를 참조해 주십시오.

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

이 메서드를 클래스 컴포넌트로 이행할 수 있습니까?

리액트 매뉴얼:https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html 에서 입수

소품 변경이 Anti Pattern일 때 상태 지우기

React 16 이후 componentWillReceiveProps는 사용되지 않습니다.반응 문서에서 이 경우 권장되는 접근법은

  1. " " " " " " " " 。ParentComponentModalBody start_time이 경우 모달은 이 상태를 소유해야 한다고 생각하기 때문에 이 방법은 선호하지 않습니다.
  2. 키를 사용하여 완전히 제어되지 않는 컴포넌트: 이것이 내가 선호하는 접근법입니다.리액트 문서의 예:https://codesandbox.io/s/6v1znlxyxn모든 것을 소유하게 될 것입니다.start_time에 기재되어 있다ModalBody및 사용getInitialState네가 이미 한 것처럼.를 리셋하려면start_timestate, 단순히 키 변경만 하면 됩니다.ParentComponent

그들의 문서를 보면 분명합니다.

If you used componentWillReceiveProps for re-computing some data only when a prop changes, use a memoization helper instead.

사용방법 : https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization

메모 사용

작전의 상태 파생은 소품을 직접 조작하는 것으로, 진정한 파생은 필요하지 않습니다.즉, 직접 활용하거나 변환할 수 있는 소품이 있는 경우 소품을 상태 그대로 저장할 필요가 없습니다.

의 상태 값이start_time단순한 소품일 뿐이다start_time.format("HH:mm")프로포트에 포함된 정보는 컴포넌트 업데이트에 이미 충분합니다.

다만, 프로포트의 변경에 관한 형식만을 호출하는 경우는, 최신의 메뉴얼에 따라서, 다음의 Memoize(https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization 를 참조해 주세요.

폼의 데이터 소스는 사용자가 입력한 경우 서브컴포넌트의 갱신을 통해 componentWillReceiveProps 또는 getDerivedStateFromProps 조작이 트리거되는 모든 상황에서 setState 실행 후 비교 후 값이 확실히 동일하지 않습니다.사용자 입력값이 변경됩니다.실수 아닌가요?

저는 ref를 사용하는 것이 안전하다고 생각합니다만, 위의 방법은 신경 쓸 필요가 없습니다.

class Company extends XComponent {
    constructor(props) {
        super(props);
        this.data = {};
    }
    fetchData(data) {
        this.resetState(data);
    }
    render() {
        return (
            <Input ref={c => this.data['name'] = c} type="text" className="form-control" />
        );
    }
}
class XComponent extends Component {
    resetState(obj) {
        for (var property in obj) {
            if (obj.hasOwnProperty(property) && typeof this.data[property] !== 'undefined') {
                if ( obj[property] !== this.data[property].state.value )
                    this.data[property].setState({value: obj[property]});
                else continue;
            }
            continue;
        }
    }
}

기능 컴포넌트와 useEffect 훅을 사용하여 다음 솔루션을 생각해냈습니다.useEffect 훅으로 소품에서 제어 특성을 감시함으로써 동작합니다.

const { useEffect, useState } = React

const Child = (props) => {
    const [bgColor, setBgColor] = useState(props.bgColor);
    const { children } = props;

    useEffect(() => {
        setBgColor(props.bgColor);
    }, [props.bgColor]);

    return (
        <div style={{ height: "100px", width: "100px", backgroundColor: bgColor }}>{children}</div>
    )
}

const Parent = (props) => {
    const [childControllingProp, setChildControllingProp] = useState(props.childControllingProp);
    const { title } = props;
    const inputRef = React.createRef();

    return (
        <>
            <input ref={inputRef} type="text" onChange={() => setChildControllingProp(inputRef.current.value)}/>
            <Child bgColor={childControllingProp}>{title}</Child>
        </>
    )
}

$(document).ready(() => {
    ReactDOM.render(
        <Parent title="Title" childControllingProp="blue"/>,
        document.querySelector("#root")
    );
})
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

<div id="root"></div>

언급URL : https://stackoverflow.com/questions/32414308/updating-state-on-props-change-in-react-form

반응형