반응 양식에서 소품 변경에 대한 상태
리액트 폼과 상태 관리에 문제가 있습니다.양식(모달)에 시간 입력 필드가 있습니다.됩니다.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_time
ModalBody
컴포넌트가 합니다.또한 하위 구성 요소가 아닌 상위 구성 요소에서 시간을 업데이트해야 합니다.
React에는 이 시나리오에 대처하기 위한 몇 가지 힌트가 있습니다.(이 문서는 그 후 웹에서 삭제된 오래된 문서입니다.컴포넌트 소품 관련 최신 문서에 대한 링크입니다.)
을 사용하여 를 발생시키다
getInitialState
종종 "진실의 원천" 즉, 실제 데이터가 있는 곳의 중복으로 이어집니다.그 이유는getInitialState
컴포넌트가 처음 생성되었을 때만 호출됩니다.가능한 한 값을 즉시 계산하여 나중에 동기화되지 않도록 하고 유지 보수 문제를 일으키지 않도록 하십시오.
으로는 부모의props
state
렌더 메서드가 항상 프로펠러 업데이트에서 호출되는 것은 아닙니다.요.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
}
}
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. 용 2getDerivedStateFromProps
componentWillReceiveProps
어떤 이유로 키가 작동하지 않는 경우(컴포넌트를 초기화하는데 비용이 많이 들 수 있음)
「」를 사용해 .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는 사용되지 않습니다.반응 문서에서 이 경우 권장되는 접근법은
- " " " " " " " " 。
ParentComponent
ModalBody
start_time
이 경우 모달은 이 상태를 소유해야 한다고 생각하기 때문에 이 방법은 선호하지 않습니다. - 키를 사용하여 완전히 제어되지 않는 컴포넌트: 이것이 내가 선호하는 접근법입니다.리액트 문서의 예:https://codesandbox.io/s/6v1znlxyxn모든 것을 소유하게 될 것입니다.
start_time
에 기재되어 있다ModalBody
및 사용getInitialState
네가 이미 한 것처럼.를 리셋하려면start_time
state, 단순히 키 변경만 하면 됩니다.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
'itsource' 카테고리의 다른 글
JSX에서 맵을 포함한 네스트 루프를 갖는 방법은 무엇입니까? (0) | 2023.04.02 |
---|---|
Wordpress용 .mo 파일을 작성하려면 어떻게 해야 합니까? (0) | 2023.04.02 |
JSON 개체는 str, 바이트 또는 byearray여야 하며 dict가 아닙니다. (0) | 2023.04.02 |
몽고이드 아니면 몽고매퍼? (0) | 2023.04.02 |
PHP: 키를 어떻게 사용하고 유지합니까? (0) | 2023.03.28 |