답변:
상태 업데이트는 비동기 작업 이므로 여러 가지 방법이 있으므로 상태 객체를 업데이트하려면 업데이터 함수를와 함께 사용해야 합니다setState
.
1- 가장 간단한 것 :
먼저 사본을 jasper
만든 다음 다음과 같이 변경하십시오.
this.setState(prevState => {
let jasper = Object.assign({}, prevState.jasper); // creating copy of state variable jasper
jasper.name = 'someothername'; // update the name property, assign a new value
return { jasper }; // return new object jasper object
})
사용하는 대신 Object.assign
다음과 같이 작성할 수도 있습니다.
let jasper = { ...prevState.jasper };
2- 스프레드 연산자 사용 :
this.setState(prevState => ({
jasper: { // object that we want to update
...prevState.jasper, // keep all other key-value pairs
name: 'something' // update the value of specific key
}
}))
참고 : Object.assign
및 Spread Operator
단지 생성 얕은 사본을 중첩 된 객체 또는 객체의 배열을 정의 그렇다면, 당신은 다른 접근 방식이 필요합니다.
상태를 다음과 같이 정의했다고 가정하십시오.
this.state = {
food: {
sandwich: {
capsicum: true,
crackers: true,
mayonnaise: true
},
pizza: {
jalapeno: true,
extraCheese: false
}
}
}
피자 개체의 extraCheese를 업데이트하려면 :
this.setState(prevState => ({
food: {
...prevState.food, // copy all other key-value pairs of food object
pizza: { // specific object of food object
...prevState.food.pizza, // copy all pizza key-value pairs
extraCheese: true // update value of specific key
}
}
}))
할 일 앱이 있고 다음 형식으로 데이터를 관리한다고 가정합니다.
this.state = {
todoItems: [
{
name: 'Learn React Basics',
status: 'pending'
}, {
name: 'Check Codebase',
status: 'pending'
}
]
}
할 일 객체의 상태를 업데이트하려면 배열에서 맵을 실행하고 각 객체의 고유 한 값을 확인하십시오.의 경우 condition=true
업데이트 된 값을 가진 새 객체를 반환하고 그렇지 않으면 동일한 객체를 반환하십시오.
let key = 2;
this.setState(prevState => ({
todoItems: prevState.todoItems.map(
el => el.key === key? { ...el, status: 'done' }: el
)
}))
제안 : 객체에 고유 한 값이 없으면 배열 색인을 사용하십시오.
jasper
개체 에서 다른 속성을 제거합니다 , console.log(jasper)
당신은 하나의 키만 볼 수 있습니다 name
, 나이는 없을 것입니다 :)
jasper
입니다 object
수행이 아니라, 다른 더 나은 솔루션 : 가능있을 수 있습니다 최고의 있는지 여부
Object.assign
연산자 딥 카피 속성을 확산 시키지도 말고 여기에 언급하는 것이 좋습니다 . 이런 식으로 lodash deepCopy
등과 같은 해결 방법을 사용해야합니다 .
let { jasper } = this.state
?
가장 빠르고 읽기 쉬운 방법입니다.
this.setState({...this.state.jasper, name: 'someothername'});
this.state.jasper
이미 이름 속성이 포함되어 있어도 새 이름 name: 'someothername'
이 사용됩니다.
this.state.jasper
반드시 최신 상태를 포함 할 필요는 없습니다. 로 표기법을 사용하는 것이 prevState
좋습니다.
이 솔루션을 사용했습니다.
다음과 같이 중첩 된 상태 인 경우 :
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입니다. 상태 객체에 사용 된 것과 동일한 이름 (이 경우 'friendName')을 사용해야합니다.
<input type="text" onChange={this.handleChange} " name="friendName" />
statusCopy.formInputs[inputName] = inputValue;
여기에 많은 답변이 있다는 것을 알고 있지만 setState 외부에서 새 객체의 복사본을 만든 다음 단순히 setState ({newObject})를 작성하는 사람이 아무도 없습니다. 깨끗하고 간결하며 신뢰할 수 있습니다. 따라서이 경우 :
const jasper = { ...this.state.jasper, name: 'someothername' }
this.setState(() => ({ jasper }))
또는 동적 속성 (매우 유용한 양식)
const jasper = { ...this.state.jasper, [VarRepresentingPropertyName]: 'new value' }
this.setState(() => ({ jasper }))
첫 번째 경우는 실제로 구문 오류입니다.
나머지 구성 요소를 볼 수 없기 때문에 왜 여기에 상태에 객체를 중첩시키는 지 알기가 어렵습니다. 구성 요소 상태에 개체를 중첩시키는 것은 좋지 않습니다. 초기 상태를 다음과 같이 설정하십시오.
this.state = {
name: 'jasper',
age: 28
}
이렇게하면 이름을 업데이트하려면 다음을 호출하면됩니다.
this.setState({
name: 'Sean'
});
그것이 당신이 목표로하는 것을 달성 할 것입니까?
더 크고 복잡한 데이터 저장소의 경우 Redux와 같은 것을 사용합니다. 그러나 훨씬 더 발전했습니다.
구성 요소 상태의 일반적인 규칙은 구성 요소의 UI 상태 (예 : 활성, 타이머 등)를 관리하는 데만 사용하는 것입니다.
다음 참조를 확인하십시오.
간단하고 역동적 인 방법.
이것은 작업을 수행하지만 모든 ID를 부모로 설정해야 부모가 개체의 이름을 가리 키도록 id = "jasper"가되고 입력 요소의 이름이 개체 재스퍼 내부의 속성임을 나타내도록합니다. .
handleChangeObj = ({target: { id , name , value}}) => this.setState({ [id]: { ...this.state[id] , [name]: value } });
당신은 이것을 시도 할 수 있습니다 : ( 주 : 입력 태그의 이름 === 객체의 필드)
<input name="myField" type="text"
value={this.state.myObject.myField}
onChange={this.handleChangeInpForm}>
</input>
-----------------------------------------------------------
handleChangeInpForm = (e) => {
let newObject = this.state.myObject;
newObject[e.target.name] = e.target.value;
this.setState({
myObject: newObject
})
}
이것은 immer immutabe 유틸리티를 사용하는 또 다른 솔루션으로 , 깊게 중첩 된 객체에 매우 적합하며 돌연변이에 신경 쓰지 않아야합니다.
this.setState(
produce(draft => {
draft.jasper.name = 'someothername
})
)
당신은 이것을 시도 할 수 있습니다 :
this.setState(prevState => {
prevState = JSON.parse(JSON.stringify(this.state.jasper));
prevState.name = 'someOtherName';
return {jasper: prevState}
})
또는 다른 재산 :
this.setState(prevState => {
prevState = JSON.parse(JSON.stringify(this.state.jasper));
prevState.age = 'someOtherAge';
return {jasper: prevState}
})
또는 handleChage 함수를 사용할 수 있습니다.
handleChage(event) {
const {name, value} = event.target;
this.setState(prevState => {
prevState = JSON.parse(JSON.stringify(this.state.jasper));
prevState[name] = value;
return {jasper: prevState}
})
}
HTML 코드 :
<input
type={"text"}
name={"name"}
value={this.state.jasper.name}
onChange={this.handleChange}
/>
<br/>
<input
type={"text"}
name={"age"}
value={this.state.jasper.age}
onChange={this.handleChange}
/>
age
내부 의 속성 을 잃어 버렸을 것jasper
입니다.