소스코드 : https://github.com/leaveittogod0123/ReactLab
state에 참조값 형태의 state의 경우에는 데이터를 수정하지 않고,
새로운 객체나 배열에 값을 복사해 수정하는 방법을 사용해야합니다.
state 값을 수정할때는 this.setState({ })
함수를 사용했죠.
배열의 경우는 concat를 사용해요 추가한 새로운 배열을 전달합니다.
this.setState({
list: this.state.list.concat(newObj);
})
다른 방법으로는 Immutability Helper
를 사용하는 방법
또 다른 방법 spread operator
를 사용하는 방법
this.state = {
a: "1",
b: "2",
c: {
d: "3",
e: "4",
f: {
change_this_value : "0",
this_stays_name: "6"
}
}
}
...
this.setState({
...this.state,
c: {
...this.state.c,
f: {
...this.state.c.f,
change_this_value: "5"
}
}
})
spread operator는 배열에서 마찬가지로 동작합니다.
추가 삭제
//추가
const array = [1,2,3,4,5];
const newArray = [...array, 7];
console.log(JSON.stringify(newArray, null, 2));
// 삭제
const array = [1,2,3,4,5];
const newArray = [...array.slice(0,2), "수정",...array.slice(3,array.length-1)];
상위 컴포넌트 Contact
에 연락처 객체를 state로 관리하고 있습니다.
하위 컴포넌트 ContactCreate
를 생성해서 데이터를 입력받아 Contact의 연락처 객체에 값을 추가할 것입니다.
render() {
return (
<div>
<h2>Create Contact</h2>
<div>
<input
type="text"
name="name"
placeholder="name"
value={this.state.name}
onChange={this.handleChange}
/>
<input
type="text"
name="phone"
placeholder="phone"
value={this.state.phone}
onChange={this.handleChange}
/>
</div>
<button type="button" onClick={this.handleClick}>
Create
</button>
</div>
);
}
constructor(props) {
super(props);
this.state = {
name: "",
phone: "",
};
}
handleChange = (e) => {
const nextState = {};
nextState[e.target.name] = e.target.value;
this.setState(nextState);
};
그리고 하위컴포넌트에서는 이벤트를 통해 내려온 메서드로 데이터를 추가합니다.
상위 컴포넌트에서 state를 수정할 메서드를 하위컴포넌트로 내려보냄
return (
<div>
...
<ContactCreate onCreate={this.handleCreate} /> <-
</div>
);
하위 컴포넌트에서는 내려받은 메서드를 실행
handleClick = () => {
const { name, phone } = this.state;
const contact = { name, phone }; //Object Property Value Shorthand
this.props.onCreate(contact);
this.setState({
name: "",
phone: "",
});
};
레퍼런스 : Object Property Value Shorthand in JavaScript with ES6 - alligator
render() {
const details = (
<div>
<p>{this.props.contact.name}</p>
<p>{this.props.contact.phone}</p>
</div>
);
const edit = (
<div>
<p>
<input
type="text"
name="name"
placeholder="name"
value={this.state.name}
onChange={this.handleChange}
/>
</p>
<p>
<input
type="text"
name="phone"
placeholder="phone"
value={this.state.phone}
onChange={this.handleChange}
/>
</p>
</div>
);
const view = this.state.isEdit ? edit : details;
const blank = <div>NotSelected</div>;
return (
<div>
<h1>Selected Contact</h1>
<div>{this.props.isSelected ? view : blank}</div>
<button type="button" onClick={this.handleToggle}>
{this.state.isEdit ? "OK" : "Edit"}
</button>
<button type="button" onClick={this.props.onRemove}>
Remove
</button>
</div>
);
}
constructor(props) {
super(props);
this.state = {
isEdit: false,
name: "",
phone: "",
};
}
handleChange = (e) => {
const nextState = {};
nextState[e.target.name] = e.target.value;
this.setState(nextState);
};
handleToggle = () => {
if (!this.state.isEdit) { <- 수정버튼을 클릭시 입력칸에 데이터를 바인딩합니다.
this.setState({
name: this.props.contact.name,
phone: this.props.contact.phone,
});
} else {
this.handleEdit(); <- 수정이 완료되었으면 상위컴포넌트의 값을 수정하는 메서드를 호출합니다.
}
this.setState({
isEdit: !this.state.isEdit,
});
};
handleEdit = () => {
this.props.onEdit(this.state.name, this.state.phone);
};
this.setState({})
은 비동기입니다.
그래서 isEdit 초기값이 false이면, 버튼을 클릭시에 false가 출력될 것입니다.
console.log(isEdit);
isEdit를 사용하고 싶으시면 !isEdit, 또는 e.target.value를 사용하셔야됩니다.
handleEdit = () => {
this.setState({
isEdit: !this.state.isEdit,
});
console.log(isEdit);
};