App 컴포넌트 내부에서 handleCreate
메소드를 만든다. 이 메소드를 자식 컴포넌트(PhonrForm.js)에 props로 전달해주고, props로 전달한 함수를 자식 컴포넌트에서 호출시켜서 data값이 App에 전달되도록 하면 된다.
App.js
에서 handleCreate
메서드를 생성해준다.
// App.js
handleCreate = (data) => {
console.log(data);
}
render() {
return (
<div>
<PhoneForm onCreate={this.handleCreate} />
</div>
);
}
}
PhoneForm.js
로 돌아와서 <input />
아래에 <button>
태그를 생성해준다.
// PhoneForm.js
<button type="submit">등록</button>
<button>
을 눌러 submit할 경우 작동할 이벤트를 handleSubmit
으로 생성해준다.
// PhoneForm.js
handleSubmit = (e) => {
e.preventDefault(); // 이벤트 발생 시 새로고침을 방지해준다.
// App.js에서 props로 받았던 onCreate를 호출해준다.
this.props.onCreate({
name: this.state.name,
phone: this.state.phone
})
// this.props.onCreate(this.state)로 작성해도 상관없다.
}
.....
.....
<form onSubmit={this.handleSubmit}>
.....
</form>
input에 입력 후 [등록]버튼을 눌러 submit하게 되면 콘솔창에서 입력한 값을 확인할 수 있다.
지금까지 작업을 통해 App.js
에서 PhoneForm.js
의 데이터를 받아올 수 있었다.
이제 PhoneForm.js
에서 받아온 데이터를 App.js
의 상태에 담아줘보자.
App.js
에서 생성했던 handleCreate
메서드를 이용해 받아온 데이터를 state에 넣어준다.
// App.js
class App extends Component {
// PhoneForm에서 받아온 데이터를 App.js의 상태에 담아줘보자.
// 1. state를 생성해 information배열을 만들어준다.(이 배열에 받아온 데이터를 넣어줄 것이다.)
state = {
information: [],
}
handleCreate = (data) => {
// PhoneForm에서 받아온 데이터를 App.js의 상태에 담아줘보자.
console.log(data);
// *** 아래 두 가지 방법처럼 작성하면 안된다!!!
// this.state.information.push(data)
// this.setState({
// information: this.state.information.push(data)
// })
// *** 그 이유: 리액트는 불변성을 유지시켜줘야 한다.
// 어떤 값을 수정하게 될 때 꼭 setState를 사용해야 하고, 그 내부에 있는 배열이나 객체를 바꾸게 될 경우 기존의 배열/객체를 바꾸는 것이 아니라 기존의 배열/객체를 기반으로 새로운 배열/객체를 만들어서 값을 주입해줘야한다.
// 따라서 concat이라는 내장함수를 사용해줘야한다.
this.setState({
information: this.state.information.concat(data)
})
}
render() {
...
...
}
}
리액트는 불변성을 유지시켜줘야 한다.
어떤 값을 수정하게 될 때 꼭 setState를 사용해야 한다.
그 내부에 있는 배열이나 객체를 바꾸게 될 경우 기존의 배열/객체를 바꾸는 것이 아니라 기존의 배열/객체를 기반으로 새로운 배열/객체를 만들어서 값을 주입해줘야한다.따라서 concat이라는 내장함수를 사용해줘야한다.
handleCreate
메서드를 비구조화 문법을 이용해서 보다 간단하고 가독성도 높아지게 수정해주면 좋다.
// App.js
handleCreate = (data) => {
const { information } = this.state; // 비구조화 할당 문법을 이용해 handleCreate메서드를 좀 더 간편하게 수정할 수 있다.(코드가 길어지는 것을 방지 + 가독성 높여줌)
this.setState({
information: information.concat(data)
})
}
PhoneForm.js
로 돌아와서 input값을 submit할 경우 기존 입력 값들을 초기화되도록 해주자.
handleSubmit = (e) => {
e.preventDefault(); // 이벤트 발생 시 새로고침을 방지해준다.
// App.js에서 props로 받았던 onCreate를 호출해준다.
this.props.onCreate({
name: this.state.name,
phone: this.state.phone
})
// this.props.onCreate(this.state)로 작성해도 상관없다.
// input값을 submit할 경우 기존 입력 값들을 초기화 시켜주자.
this.setState({
name: '',
phone: '',
})
}
App.js
의 클래스 컴포넌트 상단에 초기 id
값을 0으로 입력해준다.
class App extends Component {
id = 0;
...
...
}
id값을 state에서 작성하지 않은 이유는 id값은 렌더링되는 값이 아니기 때문이다.
💡 setState를 하는 이유는 어떤 값이 수정되었을 때 리렌더링을 하기 위함이다.
handleCreate
메서드에서 받아온 데이터를 배열에 넣을 때마다 id값이 추가되도록 수정해준다.
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat({
...data,
id: this.id++
})
})
}
id값을 넣어준 이유는 배열을 렌더링 할 때 고유한 key값이 필요하기 때문에 넣어준 것이다.
id를 넣어주는 또다른 방법들을 살펴보자.
// 방법 1)
information: information.concat(Object.assign({}, data, {
// 빈 객체에 data를 넣어주고, 마지막에 적은 {id}도 빈 객체에 넣어주겠다는 의미이다.
id: this.id++
}))
// 방법 2)
information: information.concat({
name: data.name,
phone: data.phone,
id: this.id++
})