create-react-app my-telephone
src
|
component - App.js 이동
부트스트랩 설치
yarn add bootstrap@3.4.1
src/index.js(상위컴포넌트에 부트스트랩라이브러리 등록)

Contact.js
import React, { Component } from 'react';
import ContactDetails from './ContactDetails';
//추가
import ContactInfo from './ContactInfo';
//추가(배열의 추가,삭제,수정)->update
import update from 'react-addons-update';
import ContactCreate from './ContactCreate';
class Contact extends Component {
//1.데이터관리(추가,수정,삭제,조회)->생성자를 통해서 초기화
constructor(props){
super(props);
this.state={
keyword:'', /* 실시간으로 입력할 데이터를 저장할 속성명*/
selectedKey:-1, /* 선택한 항목저장 */
//(2)배열의 초기화
contactData:[ //this.state.contactData[1]
{name:'홍길동',phone:'010-123-9876'},
{name:'테스트',phone:'010-666-9999'},
{name:'임 시',phone:'010-123-2222'},
{name:'임시2',phone:'010-123-3333'},
{name:'테스트김',phone:'010-123-4444'}
]
}
//이벤트 연결구문=>onChange={this.handleChange.bind(this)}
this.handleChange=this.handleChange.bind(this)
this.handleClick=this.handleClick.bind(this)
//추가
this.handleCreate=this.handleCreate.bind(this)
this.handleEdit=this.handleEdit.bind(this)
this.handleRemove=this.handleRemove.bind(this)
}
///배열의 추가,수정,삭제 함수선언//
handleCreate(contact){
this.setState({
//형식)배열의 키명:update(1.집어넣을 데이터대상자,2.$push이용[]로 묶어줄것)
contactData:update(this.state.contactData,{$push:[contact]})
})
}
handleEdit(name,phone){ //데이터 수정(,addr,sung,position,,,)
this.setState({
contactData:update(this.state.contactData,{
//2.수정할값에 대한 인덱스번호:{키명:{$set:수정할값},,}
[this.state.selectedKey]:{
name:{$set:name}, //형식)name(키명):{$set:저장할값}
phone:{$set:phone}//,addr:{$set:addr(서울시 강남구)}
}
})
})
}
handleRemove(){//데이터 삭제
//추가->선택하지 않으면 삭제되지않게 설정
if(this.state.selectedKey < 0){
return; //밑의 삭제하는 구문 실행하지 않고 종료
}
this.setState({
contactData:update(this.state.contactData,{
//$splice키를 이용해서 선택된 키로부터 몇개를 삭제?
//삭제할 대상자도 배열로 묶어준다.(1개라도)
//selectedKey(현재 행)을 기준해서 1개삭제
$splice:[[this.state.selectedKey,1]]
}),
selectedKey:-1 //다시 삭제시킬 대상자를 선택하기위해서 초기화
})
}
//이벤트처리해주는 함수작성
handleChange(e){ //const handleChange=(e)=>{}
//jQuery->$(this)->event.target(이벤트가 발생된 객체)
this.setState({keyword:e.target.value})
}
//key값을 매개변수로 처리해주는 함수
handleClick(key){
this.setState({selectedKey:key})
console.log(key,'is selected!')
}
//render 함수전에 호출-> DB에 저장된 데이터를 가져와서 출력
componentWillMount(){ //localStorage.contactData(키명)
const contactData=localStorage.contactData
if(contactData){ //불러올 데이터가 있다면
this.setState({
contactData:JSON.parse(contactData) //문자열->객체변환(저장)
})
}
}
//화면에 데이터를 수정할떄마다 호출
componentDidUpdate(prevProps,prevState){
//이미 저장된 과거의 데이터와 현재 데이터가 다르면 서로 비교
if(JSON.stringify(prevState.contactData)!=JSON.stringify(this.state.contactData)){
localStorage.contactData=JSON.stringify(this.state.contactData)
}
console.log('componentDidUpdate()호출됨!')
}
render() {
//화살표함수를 이용=>하나씩 분리해서 인덱스별로 출력
const mapToComponents=(data)=>{
//---추가(검색한 데이터를 찾아서 필터)->ContactInfo전달
data=data.sort()//1.정렬
data=data.filter((contact)=>{
//검색할 데이터가 없다면 indexOf()->-1리턴(못찾음)
return contact.name.indexOf(this.state.keyword) > -1;
}) //2.정렬된 데이터중에서 찾은데이터만
//---const 함수명=()=>{}
//console.log('검색한 data=>',data)//배열전체 or 일부
return data.map((contact,i)=>{
//contact(배열의 각각요소를 의미),i=>요소의 인덱스번호
//console.log('contact->',contact,'i->',i)
//부->자식(props)->문자,숫자,함수,객체도 전달
//key->내부적인 contact를 구분하는 인자->배열의 인덱스번호
//각 객체을 구분해주는 인덱스i를 여기에서 처리
/*
const test=()=> //function test()
this.handleClick(i) =>this.props.onClick
*/
return(<ContactInfo contact={contact} key={i}
onClick={()=>this.handleClick(i)}/>)
})
}
return (
<div>
<div class="form-group">
<label for="Name">검색</label>
<input name="keyword" placeholder="Search"
class="form-control" value={this.state.keyword}
onChange={this.handleChange}/>
</div>
<div>
{mapToComponents(this.state.contactData)}
<ContactDetails
isSelected={this.state.selectedKey!= -1}
contact={this.state.contactData[this.state.selectedKey]}
onRemove={this.handleRemove}
onEdit={this.handleEdit}/>
<ContactCreate onCreate={this.handleCreate}/>
{/*
<div>홍길동 010-1234-0987</div>
<div>테스트 010-1234-8888</div>
<div>임 시 010-444-0987</div>
<div>임시2 010-1234-1111</div>
<div>테스트김 010-7777-0987</div>*/}
</div>
</div>
);
}
}
export default Contact;
App.js
import React, { Component } from 'react';
//추가
import Contact from './Contact';
class App extends Component {
render() {
return (
<div>
<h1 className="text-center">전화번호부</h1>
{/* (1)
<div>홍길동 010-1234-0987</div>
<div>테스트 010-1234-8888</div>
<div>임 시 010-444-0987</div>
<div>임시2 010-1234-1111</div>
<div>테스트김 010-7777-0987</div> */}
<Contact />
</div>
);
}
}
export default App;
ContactCreate.js
import React, { Component } from 'react';
export default class ContactCreate extends Component {
//생성자->create버튼을 누르기전까지는 임시로 입력한 값을 저장
constructor(props){
super(props)
this.state={
name:'',
phone:''//,addr:'',sung:'',,,, 입력한 갯수 설정
}
this.handleChange=this.handleChange.bind(this)
this.handleKeyPress=this.handleKeyPress.bind(this)
this.handleClick=this.handleClick.bind(this)
}
//enter칠때 추가버튼을 클릭
handleKeyPress(e){//마우스좌표(x,y),특정한키(charCode),이벤트발생
if(e.charCode==13){//enter를 눌렀다면
this.handleClick()//추가버튼
}
}
//추가
handleChange(e){//event객체->값을 입력,마우스좌표값(x,y)
let nextState={} //빈객체 생성 {name:'홍길동',phone:'02-123-1111'}
//nextState[name]='홍길동' e.target->입력하고 있는 input
nextState[e.target.name]=e.target.value
this.setState(nextState)
}
//추가2
handleClick(){ //부모함수를 호출(저장할값->초기화)
const contact={
name:this.state.name,
phone:this.state.phone//,addr:this.state.addr,,,
}
//부모함수를 호출해서 전달
this.props.onCreate(contact)//handleCreate(저장할값)
//저장하고나서 초기화작업->''
this.setState({
name:'',
phone:''
})
}
render() {
return (
/* before
<div>
<p>
<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} />
</p>
<button onClick={this.handleClick}>Create</button>
</div>*/
<div class="container">
<div class="col-sm-6 col-md-offset-3">
<div class="form-group">
<label for="name">이름</label>
<input type="text" class="form-control" id="name"
name="name" placeholder="이름을 입력"
value={this.state.name}
onChange={this.handleChange} />
</div>
<div class="form-group">
<label for="name">전번</label>
<input type="text" class="form-control" id="phone"
name="phone" placeholder="전화번호를 입력"
value={this.state.phone}
onChange={this.handleChange}
onKeyPress={this.handleKeyPress} />
</div>
<div class="form-group text-center">
<button onClick={this.handleClick}
class="btn btn-success">추가</button>
</div>
{/* </form> */}
</div>
</div>
)
}
}
ContactDetail.js
import React, { Component } from 'react';
class ContactDetails extends Component {
//추가(편집상태확인)
constructor(props){
super(props)
this.state={
isEdit:false, //편집유무 체크속성
name:'',
phone:''
}
this.handleToggle=this.handleToggle.bind(this)
this.handleChange=this.handleChange.bind(this)
//추가
this.handleEdit=this.handleEdit.bind(this)
}
//부모함수호출할 함수작성
handleEdit(){
this.props.onEdit(this.state.name,this.state.phone)
}
handleToggle(){ //화면전환(true(보여주면서 편집<->false(보여주기만))
//부모의 handleEdit를 호출할 수있도록 추가코딩
//편집상태라면
if(!this.state.isEdit){//수정
this.setState({
name:this.props.contact.name,
phone:this.props.contact.phone //
//,addr:this.props.contact.addr
//,age:this.props.contact.age
})
}else{//수정할거 다하고나서 확인버튼(false)
this.handleEdit()//자기 클래스내부에서 다른 함수호출시
} //this.호출할함수명(~)
this.setState({
isEdit:!this.state.isEdit
})
//위의 setState()가 실행이 되기전에 먼저 console문장을 수행
console.log(!this.state.isEdit)
}
//추가(handleChange)ContactCreate.js에서 복사해올것.
handleChange(e){//event객체->값을 입력,마우스좌표값(x,y)
let nextState={} //빈객체 생성 {name:'홍길동',phone:'02-123-1111'}
//nextState[name]='홍길동' e.target->입력하고 있는 input
nextState[e.target.name]=e.target.value
this.setState(nextState)
}
//--------------------
render() {
//추가 선택한 항목이 있으면 항목출력,-1 (선택X 하지않음을 표시)
const details=(<div>
<p>{this.props.contact.name}</p>
<p>{this.props.contact.phone}</p>
</div>)
//추가
//const view=this.state.isEdit?(<div></div>):details;
const edit=(
<div>
<div class="col-sm-6 col-md-offset-3">
<div class="form-group">
<label for="name">이름</label>
<input type="text" class="form-control" id="name"
name="name" placeholder="이름을 입력"
value={this.state.name}
onChange={this.handleChange} />
</div>
<div class="form-group">
<label for="name">전번</label>
<input type="text" class="form-control" id="phone"
name="phone" placeholder="전화번호를 입력"
value={this.state.phone}
onChange={this.handleChange} />
</div>
</div>
</div>
)
//선택한 상태(글상세보기에서 수정버튼을 눌렀는지유무)
const view=this.state.isEdit?edit:details;
const blank=(<div>Not Selected!!!</div>)
//Contact.js에서 isSelected={선택한 항목의 index}
return (
<div className="text-center text-success">
{this.props.isSelected?view:blank}
<p>
<button onClick={this.handleToggle}
class="btn btn-info">
{this.state.isEdit?'확인':'수정'}
</button>
<button onClick={this.props.onRemove} class="btn btn-danger">삭제</button>
</p>
</div>
);
}
}
//처음에는 선택을 할 수가 없기때문에 에러발생->화면에 출력X
/*
String pageNum=request.getParameter("pageNum");
if(pageNum==null) pageNum="1"->1
*/
ContactDetails.defaultProps={
contact:{
name:'',
phone:''//,addr:'',sung:'',,,
},
//함수의 경우 초기값을 설정보다는 에러메세지를 출력
onRemove:()=>{console.error('onRemove not defined!')}
}
export default ContactDetails;
ContactInfo.js
import React, { Component } from 'react';
class ContactInfo extends Component {
//자식함수<- this.props.onClick(key)
render() {
/*
this.props.contact(전달된 배열요소의 값)->키명분리
return (
<div>
{this.props.contact.name} {this.props.contact.phone}
</div>
);*/
return (
<div className="container">
<table className="table table-bordered">
<tr className="success">
<td onClick={this.props.onClick}>{this.props.contact.name}</td>
</tr>
</table>
</div>)
}
}
export default ContactInfo;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
//추가
import App from './components/App';
//추가
import 'bootstrap/dist/css/bootstrap.css';
//-----------------------------------------
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
'KIC > React' 카테고리의 다른 글
| [React] Props, State (0) | 2020.11.04 |
|---|---|
| [React] Component 분리/모듈화 (0) | 2020.11.04 |
| [React] Component 분리 (0) | 2020.11.04 |
| [React] 라이브러리(cdn) 예제(react, reactDOM, babel) (0) | 2020.11.03 |
| [React] JSX(JavaScript Expression)문법/ 예제(기본설정,백업,복사) (0) | 2020.11.03 |