프로젝트 생성하기
앞서 배웠던 지식들을 응용하여 다양한 작업들을 구현하고, input 상태를 관리하는 방법과 배열을 다루는 방법을 알아보기 위해 새로운 프로젝트를 만들어보자.
create-react-app phone-book
해당 디렉토리를 VSCode로 열고, 내부에서 yarn start 를 통해 개발서버를 시작해보자.
첫번째 컴포넌트, PhoneForm 만들기
먼저 만들 컴포넌트는 PhoneForm이다. 이 컴포넌트에서는 사용자에게서 이름과 전화번호를 입력받을 것이다.
input 다루기
우선, src 디렉토리 내부에 components 라는 하위 디렉토리를 만든다. 그 안에 PhoneForm.js 파일을 만든다.
//src/components/PhoneForm.js
import React, { Component } from 'react';
class PhoneForm extends Component {
state = {
name: ''
}
handleChange = (e) => {
this.setState({
name: e.target.value
})
}
render() {
return (
<form>
<input
placeholder="이름"
value={this.state.name}
onChange={this.handleChange}
/>
<div>{this.state.name}</div>
</form>
);
}
}
export default PhoneForm;
onChange 이벤트가 발생하면 handleChange 함수가 호출된다. e.target.value 값을 통하여 이벤트 객체에 담겨있는 현재의 텍스트 값을 읽어올 수 있다. 해당 값을 state의 name 부분으로 설정한다.
render 부분에서 input을 렌더링 할 때는 value값과 onChange 값을 넣어주었다. onChange는 input의 텍스트 값이 바뀔때마다 발생하는 이벤트이다. 여기에 handleChange를 설정했다. 나중에 데이터를 등록하고 나면 이 name 값을 다시 공백으로 초기화하기 위해 state의 name을 ''으로 초기화하고, value에 설정해두었다. 하단에는 name 값이 잘 바뀌고 있는지 확인할 수 있도록 <div> 태그 안에 this.state.name 값을 렌더링해주었다.
해당 컴포넌트를 App에서 렌더링하여 보여주면,
와 같은 화면이 나타나게된다.
전화번호부에는 전화번호도 들어가야하기 때문에 input을 하나 더 추가해야한다. input이 여러개라면 어떻게 처리해야할까?
//src/components/PhoneForm.js
import React, { Component } from 'react';
class PhoneForm extends Component {
state = {
name: '',
phone: ''
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
});
}
render() {
return (
<form>
<input
placeholder="이름"
value={this.state.name}
onChange={this.handleChange}
name="name"
/>
<input
placeholder="전화번호"
value={this.state.phone}
onChange={this.handleChange}
name="phone"
/>
<div>{this.state.name} {this.state.phone}</div>
</form>
);
}
}
export default PhoneForm;
또 다른 이벤트 핸들러 함수를 만들수도 있겠지만, 더 나은 방법이 있다.
바로, input의 name 속성을 사용하는 것이다. render 부분을 보면, 각 input에 name 값을 "name", "phone"으로 부여해주었다. 이를 통하여 각 input을 구분할 수 있게 되었다. 이 name 속성의 값은 event.target.name 을 통해 조회할 수 있다. setState 내부에서 사용된 문법은 Computed property names (?) 라는 문법이다.
부모 컴포넌트에게 정보 전달하기
이제 state에 있는 값들을 부모 컴포넌트에게 전달해 줄 차례이다. 이런 상황에서는 부모 컴포넌트에서 메소드를 만들고, 이 메소드를 자식에게 전달한 다음 자식 내부에서 호출하는 방식을 사용한다.
App에서 handleCreate라는 메소드를 만들고, 이를 PhoneForm에게 전달해주겠다. 그리고 PhoneForm 쪽에 버튼을 만들어 submit이 발생하면 props로 받은 함수를 호출하여 App에서 파라미터로 받은 값을 사용할 수 있도록 하겠다.
//src/App.js
import React, { Component } from 'react';
import PhoneForm from './components/PhoneForm';
class App extends Component {
handleCreate = (data) => {
console.log(data);
}
render() {
return (
<div>
<PhoneForm
onCreate={this.handleCreate}
/>
</div>
);
}
}
export default App;
그 다음에는 PhoneForm에서 버튼과 onSubmit 이벤트를 설정하겠다.
//src/components/PhoneForm.js
import React, { Component } from 'react';
class PhoneForm extends Component {
state = {
name: '',
phone: ''
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
handleSubmit = (e) => {
// 페이지 리로딩 방지
e.preventDefault();
// 상태값을 onCreate 를 통하여 부모에게 전달
this.props.onCreate(this.state);
// 상태 초기화
this.setState({
name: '',
phone: ''
})
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
placeholder="이름"
value={this.state.name}
onChange={this.handleChange}
name="name"
/>
<input
placeholder="전화번호"
value={this.state.phone}
onChange={this.handleChange}
name="phone"
/>
<button type="submit">등록</button>
</form>
);
}
}
export default PhoneForm;
handleSubmit 함수를 확인해보자. 맨 위에 e.preventDefault() 라는 함수가 호출됐다. 이것은 원래 이벤트가 해야하는 작업을 방지시킨다는 의미이다. 원래는 form에서 submit이 발생하면 페이지를 다시 불러오게 되는데, 그렇게 되면 현재 상태를 잃어버리게되므로 e.preventDefault()를 통해 방지해주었다. 그 다음에는 props로 받은 onCreate 함수를 호출하고 상태값을 초기화해주었다. render 부분에서는 submit 버튼을 만들고, form 부분에 onSubmit 이벤트를 등록해준다.
누구든지 하는 리액트 6편: input 상태 관리하기 | VELOPERT.LOG
이 튜토리얼은 10편으로 이뤄진 시리즈입니다. 이전 / 다음 편을 확인하시려면 목차를 확인하세요. 자, 우리가 지금까지 배웠던것들을 요약해봅시다. 컴포넌트 만들기 props 와 state LifeCycle API 딱히 배운게 그리 많지는 않죠? 그런데 이것만으로도 정말 많은 것들을 만들 수 있습니다! 리액트는, 그냥 자바스크립트와 가깝습니다. 자바스크립트를 잘 알고 있다면, 리액트 관련해서는 배울게 그리 많지는 않습니다. 앞으로 우리는 전화번호부 프로젝트
velopert.com
'Progamming > ReactJS' 카테고리의 다른 글
[벨로퍼트] 배열 다루기(2) 제거와 수정 (0) | 2019.07.12 |
---|---|
[벨로퍼트] 배열 다루기(1) 생성과 렌더링 (0) | 2019.07.12 |
[벨로퍼트] LifeCycleAPI (0) | 2019.07.12 |
[벨로퍼트] props와 state (0) | 2019.07.11 |
[벨로퍼트] JSX (0) | 2019.07.05 |
댓글