Goal 리액트를 이용해 전화번호부 구현한 내용 정리.
Prologue 작년 하반기에 리액트에 관심이 생겨 팀내 스터디를 만들어 올초 1월까지 학습하였고, 학습한 내용을 소화할겸 전화번호부를 구현해 보았다. 본 글은 1,2편으로 나누어 작성할 것이고 1편은 리액트만을 이용해 구현한 부분까지, 2편은 리덕스를 적용한 내용에 대해 포스팅할 예정이다.
Mockup 아래 그림은 구현할 전화번호부의 모습이다.
상단의 검색바에서 사람을 검색할 수 있고, 추가버튼을 눌러 전화번호부에 추가를 할 수 있다. 좌측 하단에는 검색된 사람의 리스트를 나열하며, x버튼을 눌러 전화번호부에서 삭제를 할 수 있다. 전화번호부 리스트의 사람을 선택하면 우측에 상세정보를 나타낸다.
Component 리액트로 애플리케이션 인터페이스를 설계할때 여러가지 컴포넌트로 구성할 수 있다. 아래의 그림은 먼저 그린 목업에 내가 구현할 방식으로 컴포넌트를 나눈 모습이다.
SearchBar: 검색바와 추가버튼
PhoneBookList: 전화번호 리스트
PhoneBook: 개별 전화번호와 삭제버튼
PhoneBookDetail: 전화번호 상세
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import React, { Component } from 'react' ;import SearchBar from './components/SearchBar' ;import PhoneBookList from './components/PhoneBookList' ;import PhoneBookDetail from './components/PhoneBookDetail' ;class App extends Component { render() { return ( <div> <SearchBar/> <PhoneBookList/> <PhoneDetail/> <\/div> ); } } export default App;
State 리액트 컴포넌트 내부에서 읽고 업데이트 할 수 있는 값을 지정하기위해 State를 사용한다. State는 컴포넌트 내부에서 this.state 로 접근 가능하며, 상태변경을 위해선 반드시 this.setState()로만 변경해야 한다.
allList: 전화번호부 전체리스트
selectedList: 전화번호부 검색리스트(검색용)
selectedPhoneBook: 상세보기 대상 전화번호부
inputPhoneBook: 검색 입력값
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class App extends Component { state = { allList: phoneList, selectedList: phoneList, selectedPhoneBook: '' , inputPhoneBook: '' } render() { return ( <div> <SearchBar/> <PhoneBookList/> <PhoneDetail/> <\/div> ); } } export default App;
Props props는 properties를 줄인 표현으로 컴포넌트 속성을 사용할 때 사용하는 요소이며 부모 컴포넌트(해당 컴포넌트를 불러와 사용하는 컴포넌트)에서만 설정 할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class App extends Component { state = { allList: phoneList, selectedList: phoneList, selectedPhoneBook: '' , inputPhoneBook: '' } render() { const { inputPhoneBook, selectedList, selectedPhoneBook } = this .state; return ( <div> <SearchBar inputPhoneBook={inputPhoneBook} /> <PhoneBookList phoneBookList={selectedList}/> <PhoneDetail phoneBook={selectedPhoneBook}/> <\/div> ); } } export default App;export default class SearchBar extends Component { render() { return ( <div> <input type="text" value={this .props.inputPhoneBook} placeholder="Search.." /> <div> <button type="button" >추가<\/button> <\/div> <\/div> ) } }
Event Handling 리액트의 이벤트 시스템은 html 이벤트와 사용법이 매우 비슷하지만 주의할 점이 있다.
이벤트 이름은 camelCase로 작성한다.(예: onclick => onClick, onkeyup => onKeyUp)
이벤트에 실행할 자바스크립트 코드를 전달하는것이 아니라, 함수 형태의 값을 전달한다.
DOM 요소에만 이벤트를 설정할 수 있다.(내가 만든 컴포넌트는 이벤트를 설정 할 수 없다.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class App extends Component { (...) handleSelectedList = (e ) => { this .setState({ selectedList: this .state.allList.filter(phonebook => phonebook.name.search(e.target.value) !== -1 ), inputPhoneBook: e.target.value }); } addPhoneBook = () => { const { allList, inputPhoneBook } = this .state; const newPhoneBook = { id: this .id++, name: inputPhoneBook, phonenumber: '' , address: '' } this .setState( { allList: [...allList, newPhoneBook], selectedPhoneBook: newPhoneBook, selectedList: [newPhoneBook] }) } render() { const { inputPhoneBook, selectedList, selectedPhoneBook } = this .state; const { handleSelectedList, addPhoneBook } = this ; return ( <div> <SearchBar inputPhoneBook={inputPhoneBook} handleSelectedList = {handleSelectedList} addPhoneBook = {addPhoneBook} /> <PhoneBookList phoneBookList={selectedList}/> <PhoneDetail phoneBook={selectedPhoneBook}/> <\/div> ); } } export default App;export default class SearchBar extends Component { render() { const { inputPhoneBook, handleSelectedList, addPhoneBook } = this .props; return ( <div> <input type="text" onChange={handleSelectedList} value={inputPhoneBook} placeholder="Search.." /> <div> <button type="button" onClick={addPhoneBook}>추가<\/button> <\/div> <\/div> ) } }
Conclusion 순수 리액트만으로 전화번호부 구현 방법에 대해 살펴보았다. 구현에 대한 전체소스는 여기 에서 확인 할 수 있다.
Reference : 리액트를 다루는 기술