벨로퍼트님 8편
보고 작성한 글입니다.
import React, { Component } from 'react';
import PhoneForm from './components/PhoneForm';
import PhoneInfoList from './components/PhoneInfoList';
class App extends Component {
id = 2
state = {
information: [
{
id: 0,
name: '김민준',
phone: '010-0000-0000'
},
{
id: 1,
name: '홍길동',
phone: '010-0000-0001'
}
]
}
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat({ id: this.id++, ...data }) //새로운 정보가 form에 입력되어 전송되면,
// information에 이어 붙이는것임 id랑 들어온 data 모두
// 즉, id : this.id++
// name : 사용자가 입력한 name
// phone : 사용자가 입력한 phone 이 state.information에 저장된다.
})
}
handleRemove = (id) => {
const { information } = this.state;
this.setState({
information: information.filter(info => info.id !== id) //information을 id빼고 다시 만든거임. 덮어쓰기 한 듯(정답ㅋㅋㅋ)
})
}
handleUpdate = (id, data) => { //수정을 누른 글의 id와 data를 매개변수로 받아옴
//datasms information이구만
const { information } = this.state;
this.setState({
information: information.map(
info => id === info.id
? { ...info, ...data } // 새 객체를 만들어서 기존의 값과 전달받은 data 을 덮어씀
: info // 기존의 값을 그대로 유지
)
})
}
render() {
const { information } = this.state;
return (
<div>
<PhoneForm
onCreate={this.handleCreate}
/>
<PhoneInfoList data={information}
onRemove={this.handleRemove}
onUpdate={this.handleUpdate}/>
</div>
);
}
}
export default App;
import React, { Component } from 'react';
class PhoneForm extends Component {
state = {
name: '',
phone: '' //state에 name속성이 있어야 state.name, state.phone으로 불러올 수 있음.
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value //여기서 name은 name속성을 말하는 것인데,
//배열로 감싼 이유는 여러개 를 e.target.value로 넣어주려고 그런듯
})
}
handleSubmit = (e) => {
// 페이지 리로딩 방지 (원래 form에서 submit이 발생하면 페이지 리로딩이되는데,
// 그러면 우리가 지니고있는 상태값을 다 잃어버리므로 방지시킴)
e.preventDefault(); //원래 이벤트가 해야하는 작업 방지
// 상태값을 onCreate 를 통하여 부모에게 전달 (props로 애초에 부모인 App.js에서
// onCreate함수가 정의되어있는데, 그 함수를 그냥 쓴거다. 자식에서 그러니까
// 사실은 여기서 부모에게 전달해준다고 이해한다기 보다는 , 부모에서 PhoneForm에다가
// onCreate함수를 써놨기 때문에 상태값을 전달해줄 수밖에 없는 것이다.)
this.props.onCreate(this.state);
// 상태 초기화
this.setState({
name: '',
phone: ''
})
}
render() {
return (
// onSubmit을 안써주면 말짱도루묵ㅋㅋ
<form onSubmit={this.handleSubmit}>
<input
placeholder="이름"
value={this.state.name}
onChange={this.handleChange}
name="name" //name 속성 설정 필수
/>
<input
placeholder="전화번호"
value={this.state.phone}
onChange={this.handleChange}
name="phone"
/>
<button type="submit">등록</button>
</form>
);
}
}
export default PhoneForm;
import React, { Component } from 'react';
import PhoneInfo from './PhoneInfo';
class PhoneInfoList extends Component {
static defaultProps = {
list: [],
onRemove: () => console.warn('onRemove not defined'),
}
render() {
const { data , onRemove , onUpdate} = this.props;
const list = data.map(
info => (<PhoneInfo
key={info.id}
info={info}
onRemove={onRemove}
onUpdate={onUpdate}/>) //이 info가 저 info인지 어케알지,,,,?? => data를 하나씩 쪼갠걸 info로 불러가지구,,,,
//data가 props로 받은걸 data로 하는데 그 데이터 덩어리를 하나씩 쪼갠게 info고,,,그 info를 info로 넣겠다...?
//onRemove는 삭제할 id값이 PhoneInfo 에서 넘어온다.
);
return (
<div>
{list}
</div>
);
}
}
export default PhoneInfoList;
import React, { Component } from 'react';
class PhoneInfo extends Component {
static defaultProps = {
info: {
name: '이름',
phone: '010-0000-0000',
id: 0
},
}
state = {
// 우리는 수정 버튼을 눌렀을 떄 editing 값을 true 로 설정해줄것입니다.
// 이 값이 true 일 때에는, 기존에 텍스트 형태로 보여주던 값들을
// input 형태로 보여주게 됩니다.
editing: false,
// input 의 값은 유동적이겠지요? input 값을 담기 위해서 각 필드를 위한 값도
// 설정합니다
name: '',
phone: '',
}
handleRemove = () => {
// 삭제 버튼이 클릭되면 onRemove 에 id 넣어서 호출
const { info, onRemove } = this.props;
onRemove(info.id);
}
// editing 값을 반전시키는 함수입니다
// true -> false, false -> true
handleToggleEdit = () => {
const { editing } = this.state;
this.setState({ editing: !editing }); //true를 false로 반전시키는 기능을 하나보다
//true가 되면 수정 창이 열리는듯
}
// input 에서 onChange 이벤트가 발생 될 때
// 호출되는 함수입니다
handleChange = (e) => {
const { name, value } = e.target;
this.setState({
[name]: value
});
}
componentDidUpdate(prevProps, prevState) {//라이프생명주기 : 컴포넌트 업데이트가 끝나면 자동 실행
//prevState는 내장함수여서 자동으로 이전 상태값을 불러와준다.!!!!
// 여기서는, editing 값이 바뀔 때 처리 할 로직이 적혀있습니다.
// 수정을 눌렀을땐, 기존의 값이 input에 나타나고,
// 수정을 적용할땐, input 의 값들을 부모한테 전달해줍니다.
const { info, onUpdate } = this.props;
if(!prevState.editing && this.state.editing) {
// editing 값이 false -> true 로 전환 될 때 (수정 버튼을 눌러서 이전 정보가 input창이 열렸을 때)
// info 의 값을 state 에 넣어준다
this.setState({
name: info.name,
phone: info.phone
})
}
if (prevState.editing && !this.state.editing) {
// editing 값이 true -> false 로 전환 될 때 (수정 적용 버튼 눌렀을 때)
onUpdate(info.id, {
name: this.state.name,
phone: this.state.phone
});
}
}
render() {
const style = {
border: '1px solid black',
padding: '8px',
margin: '8px'
};
const { editing } = this.state;
if (editing) { // 수정모드
return (
<div style={style}>
<div>
<input
value={this.state.name}
name="name"
placeholder="이름"
onChange={this.handleChange}
/>
</div>
<div>
<input
value={this.state.phone}
name="phone"
placeholder="전화번호"
onChange={this.handleChange}
/>
</div>
<button onClick={this.handleToggleEdit}>적용</button>
<button onClick={this.handleRemove}>삭제</button>
</div>
);
}
//일반모드
const {
name, phone
} = this.props.info;
return (
<div style={style}>
<div><b>{name}</b></div>
<div>{phone}</div>
<button onClick={this.handleToggleEdit}>수정</button>
<button onClick={this.handleRemove}>삭제</button>
</div>
);
}
}
export default PhoneInfo;
componentDidUpdate(prevProps, prevState) 함수 역할이 굉장히 큰 거 같다.
공부가 정말 많이 필요할듯..
생명주기 안에서 해내는 일이 굉장히 많은 것 같다.
그리고 prevProps, prevState는 리액트 안에 내장 함수 여서
많이 쓰인다고 한다 .. 공부하자....