나는'm 을 구성하려고 나를 사용하여 상태의 중첩 시 다음과 같다:
this.state = {
someProperty: {
flag:true
}
}
하지만 업데이트 상태는 다음과 같이,
this.setState({ someProperty.flag: false });
지 않't work. 이것을 어떻게 할 수 있는가?
하기 위해서setState
에 대한 중첩된할 수 있는 개체를 따라 아래 방법으로 생각 setState 지 않't 손잡이 중첩 업데이트됩니다.
var someProperty = {...this.state.someProperty}
someProperty.flag = true;
this.setState({someProperty})
아이디어를 만들고 더미 개체에 대한 작업을 수행하고 다음 대체 구성 요소는's state 업데이트된체
이제,확산 연산자를 만듭 하나의 수준이 중첩된 사본의 개체입니다. 귀하의 상태가 매우 중첩된 다음과 같:
this.state = {
someProperty: {
someOtherProperty: {
anotherProperty: {
flag: true
}
..
}
...
}
...
}
할 수 있습 setState 확산을 사용하여 운전자에서 같은 각 레벨
this.setState(prevState => ({
...prevState,
someProperty: {
...prevState.someProperty,
someOtherProperty: {
...prevState.someProperty.someOtherProperty,
anotherProperty: {
...prevState.someProperty.someOtherProperty.anotherProperty,
flag: false
}
}
}
}))
그러나 위의 구문을 얻을 매긴 상태로 점점 더 중첩 그러므로 내가 당신을 사용하여`불변-도우미패키지를 업데이트 상태입니다.
이 대답하는 방법에 대한 업데이트 상태를 가진불변성 helper
.
가끔 직접 응답하지 않고 최고의 것:)
짧은 버전:
이 코드
this.state = {
someProperty: {
flag: true
}
}
간단하게 해야 한 다음과 같이
this.state = {
somePropertyFlag: true
}
긴 버전:
현재면 안됩't 하고 작업하려는 중첩된 상태에서 반응. 기 때문에 반응하지 않은 방향으로 작업 중첩국 및 모든 솔루션을 제안하기로 해킹. 그't 를 사용하여 framework 그러나 그것으로 싸움. 그들은 제안을 작성되지 않도록 명확한 코드에 대한 의심의 목적은 그룹니다. 그래서 그들은 매우 흥미로운 대한 답변으로 도전을 하지만 실질적으로 쓸모가 없다.
할 수 있습을 상상해 다음과 같은 상태:
{
parent: {
child1: 'value 1',
child2: 'value 2',
...
child100: 'value 100'
}
}
무슨 일이 일어날 변경할 경우에는 그 값이child1
? 반응하지 않을 것이다 re-렌더링하기 때문에 그것을 사용하여 얕은 비교하고 그것을 찾을 수 있는부모
산지 않았't change. BTW 변화시키고 국가 객체를 직접으로 간주됩 나쁜 연습니다.
그래서 당신을 다시 만들 필요가 전체``부모 개체입니다. 그러나 이 경우에는 다른 문제입니다. 반응하는 것이 생각하는 모든 아이들이 변경되었을 그들의 값을 렌더링의 모든니다. 물론 그것은 좋은 성능을 향상시킬 수 있습니다.
그것은 여전히 해결하기 위해 최선을 다하고 그 문제를 작성하여 복잡한 논리에shouldComponentUpdate()
그러나 내가 선호하는지 여기를 사용한 간단한 솔루션에서 짧은 버전입니다.
중첩된 상태에서 반응하는가 잘못 디자인
읽기이 우수한 답변.
뒤에 이 대답:
반응's setState 은 내 편의,하지만 당신은 곧 실현 는 한계가 있습니다. 를 사용하여 사용자 지정 특성과의 지능적인 사용 forceUpdate 당신에게 훨씬 더 있습니다. 예를 들어:
class MyClass extends 반응합니다.구성 요소{ myState=someObject inputValue=42 ...
MobX,예를 들어,도랑을 완전히 상태와 사용자 관찰 속성입니다. 사용을 관찰 가능한 대신의 상태에서 반응하는 요소를 사용합니다.
다른짧은업데이트하는 방법이 무엇이 중첩을 제공합니다.
this.setState(state => {
state.nested.flag = false
state.another.deep.prop = true
return state
})
this.setState(state=>(상태입니다.중첩.flag=false 인 상태))
이를 효과적으로 동일
this.state.nested.flag = false
this.forceUpdate()
을 위한 미묘한 차이를 이 상황에서사 forceUpdate
과setState
참된 예입니다.</하위>
물론 이것은 학대 일부 핵심 원칙으로주
로 읽어야만 하기 때문에 당신은 즉시 폐기 오래된 상태이고 그것을 대체하는 새로운 국가,그것은 완전히 확인.
도록 구성 요소를 포함하는 국가 will 업데이트 및 rerender 제(이 경우를 제외하고 잡았다),소품이 fail 을 전파하 어린이(참조하십시오 Spymaster's below). 만 이 기술을 사용하는 경우에 당신이 무엇을 하고 있다.
예를 들어,당신은 통과할 수 있는 변경 평는 소품이 업데이트되고 전달되는 쉽습니다.
render(
//some complex render with your nested state
<ChildComponent complexNestedProp={this.state.nested} pleaseRerender={Math.random()}/>
)
지금도에 대한 참조 complexNestedProp 을 변경하지 않았(shouldComponentUpdate)
this.props.complexNestedProp === nextProps.complexNestedProp
구성 요소 _will_rerender 때마다 부모는 구성 요소를 업데이트하는 경우를 호출한 후에이다.setState
또는이다.forceUpdate
에서 부모입니다.
사용중첩된 상태고 변화시키는 국가에 직접기 때문에 위험하고는 다른 물체를 잡고 있습(의도적으로 또는지)다른(구)참조국고하지 않을 수도 있습니다면 알을 업데이트(예를 들어사용하는 경우 PureComponent
또는shouldComponentUpdate
구현을 반환false
)나는 것을 표시하는 오래된 데이터는 아래 예와 같이.
상상하는 우주 비행중의 스케줄을 렌더링 역사적 데이터,돌연변이 데이터에서는 손에 예기치 못한 작동이 될 것으로도 변경은 이전 항목입니다.
어쨌든 여기에 당신이 볼 수 있는 중첩된 PureChildClass`지 rerendered 으로 인해 실패한 소품을 전파.
를 사용하는 경우 ES2015 에 액세스할 수 있다.을 할당. 당신은 그것을 사용할 수 있는 다음과 같이 업데이 중첩된 개체입니다.
this.setState({
someProperty: Object.assign({}, this.state.someProperty, {flag: false})
});
당신이 병합한 업데이트 속성으로 기존 사용 반환되는 개체를 업데이트 상태입니다.
편집:첨가 빈 객체를 대상으로 할당하는 기능을 확인 상태가 아't 돌연변이 직접 carkod 지적했다.
많은 라이브러리하는 데 도움이 됩니다. 예를 들어,사용하여불변-도우미:
import update from 'immutability-helper';
const newState = update(this.state, {
someProperty: {flag: {$set: false}},
};
this.setState(newState);
를 사용하여lodash/fp설정:
import {set} from 'lodash/fp';
const newState = set(["someProperty", "flag"], false, this.state);
를 사용하여lodash/fp병합:
import {merge} from 'lodash/fp';
const newState = merge(this.state, {
someProperty: {flag: false},
});
여기's 의 변형에서 첫 번째에서 자신이 스레드는't 필요한 모든 추가 패키지로,도서관 또는 특별한 기능이다.
state = {
someProperty: {
flag: 'string'
}
}
handleChange = (value) => {
const newState = {...this.state.someProperty, flag: value}
this.setState({ someProperty: newState })
}
하기 위해 설정 상태의 중첩된 특정 분야,당신은 집 전체 개체입니다. 내가 이것을 만들어 가변,newState
고 확산하는 내용의 현재 상태 그것으로 first 를 사용하 ES2015퍼짐 operator. 그런 다음,대체의 값을이다.상태입니다.국기와 함께 새로운 값(이후 나는
플래그 값_after_ 펼쳐 현재 상태로 개체
깃발분야에서 현재 상태가 재정). 그 후,나는 단순히 설정 상태의
someProperty나
newState`개체입니다.
우리가 사용하는 Immer https://github.com/mweststrate/immer 이러한 종류의 문제입니다.
단지 이것을 대체 코드에서 하나의 구성요소
this.setState(prevState => ({
...prevState,
preferences: {
...prevState.preferences,
[key]: newValue
}
}));
이
import produce from 'immer';
this.setState(produce(draft => {
draft.preferences[key] = newValue;
}));
와 immer 당신의 상태로"정상적인 개체를". 마법이 일어나 뒤에 장면 프록시는 개체입니다.
지만 중첩 아't 는 정말 어떻게 처리해야 합 구성 요소 상태,때로는 뭔가를 쉽게를 위한 단 하나 층 중첩이 있습니다.
에 대한 상태이
state = {
contact: {
phone: '888-888-8888',
email: '[email protected]'
}
address: {
street:''
},
occupation: {
}
}
다시 사용 가능한 방법을 사용했는데 다음과 같이 보일 것입니다.
handleChange = (obj) => e => {
let x = this.state[obj];
x[e.target.name] = e.target.value;
this.setState({ [obj]: x });
};
그냥 지나가는 obj 의 이름을 각각의 중첩을 해결하려는...
<TextField
name="street"
onChange={handleChange('address')}
/>
내가 사용하는 이 솔루션입니다.
이 있는 경우에는 중첩된 상태는 다음과 같다:
this.state = {
formInputs:{
friendName:{
value:'',
isValid:false,
errorMsg:''
},
friendEmail:{
value:'',
isValid:false,
errorMsg:''
}
}
당신이 선언할 수 있습 handleChange 기능은 해당 복사본은 현재 상태 및 재 할당으로 변경된 값
handleChange(el) {
let inputName = el.target.name;
let inputValue = el.target.value;
let statusCopy = Object.assign({}, this.state);
statusCopy.formInputs[inputName].value = inputValue;
this.setState(statusCopy);
}
여기에는 html 이벤트와 수신기
<input type="text" onChange={this.handleChange} " name="friendName" />
하는 것을 일반에@ShubhamKhatri's@Qwerty's 답변이 있습니다.
주체
this.state = {
name: '',
grandParent: {
parent1: {
child: ''
},
parent2: {
child: ''
}
}
};
입력장치 제어
<input
value={this.state.name}
onChange={this.updateState}
type="text"
name="name"
/>
<input
value={this.state.grandParent.parent1.child}
onChange={this.updateState}
type="text"
name="grandParent.parent1.child"
/>
<input
value={this.state.grandParent.parent2.child}
onChange={this.updateState}
type="text"
name="grandParent.parent2.child"
/>
*updateState 방법
setState 로@ShubhamKhatri's 응답
updateState(event) {
const path = event.target.name.split('.');
const depth = path.length;
const oldstate = this.state;
const newstate = { ...oldstate };
let newStateLevel = newstate;
let oldStateLevel = oldstate;
for (let i = 0; i < depth; i += 1) {
if (i === depth - 1) {
newStateLevel[path[i]] = event.target.value;
} else {
newStateLevel[path[i]] = { ...oldStateLevel[path[i]] };
oldStateLevel = oldStateLevel[path[i]];
newStateLevel = newStateLevel[path[i]];
}
}
this.setState(newstate);
}
setState 로@Qwerty's 응답
updateState(event) {
const path = event.target.name.split('.');
const depth = path.length;
const state = { ...this.state };
let ref = state;
for (let i = 0; i < depth; i += 1) {
if (i === depth - 1) {
ref[path[i]] = event.target.value;
} else {
ref = ref[path[i]];
}
}
this.setState(state);
}
참고:이러한 이 방법 위에 승't 작업에 대한 배열
다음 두 개의 옵션을 추가로 언급하지 않:
가 매우 심각하게 우려이 표명를 만드는 주위의 완전한 복사본 구성 요소 상태가 됩니다. 는 말했다,나는 것이 좋Immer.
import produce from 'immer';
<input
value={this.state.form.username}
onChange={e => produce(this.state, s => { s.form.username = e.target.value }) } />
이 일을 해야에 대한 반응합니다.PureComponent
(즉,얕은 국가 비교에 의해 반응)로Immer
영리하게 사용하는 프록시는 개체를 효율적으로 사본에는 임의로 깊은 상태 트리입니다. Immer 은 또한 더 많은 형식이 안전해 도서관 같은 불변성 도 이상적입니다에 대한 자바 스크립트와 타이프 라이터입니다.
타이프 라이터유틸리티 기능
function setStateDeep<S>(comp: React.Component<any, S, any>, fn: (s:
Draft<Readonly<S>>) => any) {
comp.setState(produce(comp.state, s => { fn(s); }))
}
onChange={e => setStateDeep(this, s => s.form.username = e.target.value)}
stateUpdate=()=>{ 자 obj=다.상태 는 경우(이다.props.v12_data.값이 있습니다.이메일){ obj.obj_v12.고객입니다.EmailAddress=다.props.v12_data.값이 있습니다.이메일 } 다.setState(obj) }
를 사용하는 경우 formik 프로젝트에서 그것은 몇 가지기 쉬운 방법으로 처리 및 무료 세면용품 등이 있습니다. 여기에는 가장 쉬운 방법으로 할 formik.
첫번째 초기 설정 값 내부 formik initivalues 특성 또는 반응합니다. 국가
여기에 초기 값에서 정의 반응 상태
state = {
data: {
fy: {
active: "N"
}
}
}
정의를 위 initialValues 에 대한 formik 분야 내부 formikinitiValues
특성
<Formik
initialValues={this.state.data}
onSubmit={(values, actions)=> {...your actions goes here}}
>
{({ isSubmitting }) => (
<Form>
<Field type="checkbox" name="fy.active" onChange={(e) => {
const value = e.target.checked;
if(value) setFieldValue('fy.active', 'Y')
else setFieldValue('fy.active', 'N')
}}/>
</Form>
)}
</Formik>
인 콘솔 상태를 확인 업데이트로문자열의
대신에boolean'the formik
setFieldValue`기능 상태를 설정하거나 반응하는 디버거 도구를 변화를 볼 iniside formik 상태 값입니다.
나는 이 일을 가지고 프로젝트 형태로 내 경우에는 예를 들어 있는 id,이름이 나는'd 는 오히려 상태를 유지를 위한 중첩된 프로젝트입니다.
return (
<div>
<h2>Project Details</h2>
<form>
<input label="ID" group type="number" value={this.state.project.id} onChange={(event) => this.setState({ project: {...this.state.project, id: event.target.value}})} />
<input label="Name" group type="text" value={this.state.project.name} onChange={(event) => this.setState({ project: {...this.state.project, name: event.target.value}})} />
</form>
</div>
)
알려주세요!
이런 수 있는 충분
const isObject = (thing) => {
if(thing &&
typeof thing === 'object' &&
typeof thing !== null
&& !(Array.isArray(thing))
){
return true;
}
return false;
}
/*
Call with an array containing the path to the property you want to access
And the current component/redux state.
For example if we want to update `hello` within the following obj
const obj = {
somePrimitive:false,
someNestedObj:{
hello:1
}
}
we would do :
//clone the object
const cloned = clone(['someNestedObj','hello'],obj)
//Set the new value
cloned.someNestedObj.hello = 5;
*/
const clone = (arr, state) => {
let clonedObj = {...state}
const originalObj = clonedObj;
arr.forEach(property => {
if(!(property in clonedObj)){
throw new Error('State missing property')
}
if(isObject(clonedObj[property])){
clonedObj[property] = {...originalObj[property]};
clonedObj = clonedObj[property];
}
})
return originalObj;
}
const nestedObj = {
someProperty:true,
someNestedObj:{
someOtherProperty:true
}
}
const clonedObj = clone(['someProperty'], nestedObj);
console.log(clonedObj === nestedObj) //returns false
console.log(clonedObj.someProperty === nestedObj.someProperty) //returns true
console.log(clonedObj.someNestedObj === nestedObj.someNestedObj) //returns true
console.log()
const clonedObj2 = clone(['someProperty','someNestedObj','someOtherProperty'], nestedObj);
console.log(clonedObj2 === nestedObj) // returns false
console.log(clonedObj2.someNestedObj === nestedObj.someNestedObj) //returns false
//returns true (doesn't attempt to clone because its primitive type)
console.log(clonedObj2.someNestedObj.someOtherProperty === nestedObj.someNestedObj.someOtherProperty)
내가 알고있는것은 오래된 질문이지만 공유하고 싶었을 달성하는 방법이다. 가정 국가에서 생성자를 다음과 같습니다:
constructor(props) {
super(props);
this.state = {
loading: false,
user: {
email: ""
},
organization: {
name: ""
}
};
this.handleChange = this.handleChange.bind(this);
}
나의handleChange
기능은 다음과 같다:
handleChange(e) {
const names = e.target.name.split(".");
const value = e.target.type === "checkbox" ? e.target.checked : e.target.value;
this.setState((state) => {
state[names[0]][names[1]] = value;
return {[names[0]]: state[names[0]]};
});
}
고 있는지 확인 이름을 입력에 따라:
<input
type="text"
name="user.email"
onChange={this.handleChange}
value={this.state.user.firstName}
placeholder="Email Address"
/>
<input
type="text"
name="organization.name"
onChange={this.handleChange}
value={this.state.organization.name}
placeholder="Organization Name"
/>