티스토리 뷰
데이터 제거
데이터를 제거하기 위한 몇 가지 방법이 있습니다.
1 2 3 4 5 6 7 8 | const array = [1, 2, 3, 4, 5]; // slice로 자른 후 concat으로 붙인다. array.slice(0, 2).concat(array.slice(3, 5)); // [1, 2, 4, 5] // [...array.slice(0, 2), ...array.slice(3,5)]; // 위와 같은 내용을 전개 연산자를 이용하여 표현 // 배열에서 3이 아닌 요소만 필터링 array.filter(num => num !== 3); // [1, 2, 4, 5] | cs |
이제 실제 파일을 위와 같은 제거 방법을 써서 추가해 보겠습니다.
App.js 파일을 다음과 같이 수정하세요.
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 56 | // App.js import React, { Component } from "react"; import "./App.css"; import AccountBookForm from "./components/AccountBookForm"; import AccountBookInfoList from "./components/AccountBookInfoList"; class App extends Component { // field currentId = 1; state = { list: [ { id: 0, type: "지출", price: 3800, usage: "점심 식비", date: "2019. 1. 16 오후 1:12:33" }, { id: 1, type: "수입", price: 20000, usage: "중고책 판매", date: "2019. 1. 18 오전 10:17:21" } ] }; add = data => { const { list } = this.state; this.setState({ list: list.concat({ id: ++this.currentId, ...data }) }); }; remove = id => { const { list } = this.state; this.setState({ list: list.filter(info => info.id !== id) }); }; render() { const { list } = this.state; return ( <React.Fragment> <AccountBookForm onAdd={this.add} /> <AccountBookInfoList list={list} onRemove={this.remove} /> </React.Fragment> ); } } export default App; | cs |
remove 함수를 정의하고 이 함수 내부에 filter 함수를 이용하여 해당 id를 가진 데이터를 삭제합니다. AccountBookInfoList에 이 remove 함수를 props로 전달합니다.
components/AccountBookInfoList.js 파일을 다음과 같이 수정합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // components/AccountBookInfoList.js import React, { Component } from "react"; import AccountBookInfo from "./AccountBookInfo"; class AccountBookInfoList extends Component { static defaultProps = { list: [], onRemove: () => console.warn("onRemove is not defined.") }; render() { const { list, onRemove } = this.props; const infoList = list.map(info => ( <AccountBookInfo key={info.key} data={info} onRemove={onRemove} /> )); return <React.Fragment>{infoList}</React.Fragment>; } } export default AccountBookInfoList; | cs |
App.js에서 받은 onRemove 함수를 AccountBookInfo에 props로 전달합니다.
components/AccountBookInfo.js 파일을 다음과 같이 수정합니다.
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 | // components/AccountBookInfo.js import React, { Component } from "react"; class AccountBookInfo extends Component { static defaultProps = { data: { id: 0, type: "분류", price: 0, usage: "-", date: "-" } }; remove = () => { const { data, onRemove } = this.props; onRemove(data.id); }; render() { const style = { border: "1px solid black", padding: "5px", margin: "5px" }; const { type, price, usage, date } = this.props.data; return ( <div style={style}> <div>{type}</div> <div>{price}</div> <div>{usage}</div> <div>{date}</div> <button onClick={this.remove}>삭제</button> </div> ); } } export default AccountBookInfo; | cs |
remove 함수를 정의하고 이 곳에서 App.js의 remove 함수를 실행할 수 있게 합니다. UI적으로 버튼을 추가하고 이 버튼을 클릭하면 remove 함수가 실행되도록 합니다. 결과는?
id가 1인 info에서 삭제 버튼을 클릭했을 때 결과입니다.
데이터 수정
수정할 때도 추가와 마찬가지로 불변성을 유지해야 합니다. 기존의 배열과 내부 객체를 직접 접근하지 않고, 특정 key 값의 객체를 찾아 새로운 객체로 덮어쓰는 방식으로 처리하면 됩니다.
App.js를 다음과 같이 수정해 주세요.
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | // App.js import React, { Component } from "react"; import "./App.css"; import AccountBookForm from "./components/AccountBookForm"; import AccountBookInfoList from "./components/AccountBookInfoList"; class App extends Component { // field currentId = 1; state = { list: [ { id: 0, type: "지출", price: 3800, usage: "점심 식비", date: "2019. 1. 16 오후 1:12:33" }, { id: 1, type: "수입", price: 20000, usage: "중고책 판매", date: "2019. 1. 18 오전 10:17:21" } ] }; add = data => { const { list } = this.state; this.setState({ list: list.concat({ id: ++this.currentId, ...data }) }); }; remove = id => { const { list } = this.state; this.setState({ list: list.filter(info => info.id !== id) }); }; update = (id, data) => { const { list } = this.state; this.setState({ list: list.map( info => id === info.id // 현재 수정하는 id를 찾음 ? { ...info, ...data } // 새로운 내용(data)으로 덮어씀 : info // 기존값 유지 ) }); }; render() { const { list } = this.state; return ( <React.Fragment> <AccountBookForm onAdd={this.add} /> <AccountBookInfoList list={list} onRemove={this.remove} onUpdate={this.update} /> </React.Fragment> ); } } export default App; | cs |
update라는 함수를 정의하고 AccountBookInfoList에 props로 이 함수를 전달합니다.
다음은 components/AccountBookInfoList.js 파일을 다음과 같이 수정해 주세요.
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 | // components/AccountBookInfoList.js import React, { Component } from "react"; import AccountBookInfo from "./AccountBookInfo"; class AccountBookInfoList extends Component { static defaultProps = { list: [], onRemove: () => console.warn("onRemove is not defined."), onUpdate: () => console.warn("onUpdate is not defined.") }; render() { const { list, onRemove, onUpdate } = this.props; const infoList = list.map(info => ( <AccountBookInfo key={info.key} data={info} onRemove={onRemove} onUpdate={onUpdate} /> )); return <React.Fragment>{infoList}</React.Fragment>; } } export default AccountBookInfoList; | cs |
App.js로부터 받은 onUpdate 함수를 다시 AccountBookInfo에 props로 전달합니다.
다음은 components/AccountBookInfo.js 파일을 다음과 같이 수정해 주세요.
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | // components/AccountBookInfo.js import React, { Component } from "react"; // 현재시간을 특정 format의 문자열로 반환 const getCurrentTimetoString = () => { return new Date().toLocaleString(); }; // 천 단위 구분기호를 포함한 문자열을 반환(정규식 이용) const toCommaString = num => { return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }; class AccountBookInfo extends Component { static defaultProps = { data: { id: 0, type: "분류", price: 0, usage: "-", date: "-" }, onUpdate: () => console.warn("onUpdate is not defined.") }; // 수정을 할 때, 기존의 내용이 변하므로 state를 정의 state = { editing: false, type: "", price: "", usage: "", date: "" }; remove = () => { const { data, onRemove } = this.props; onRemove(data.id); }; // 수정/적용 버튼의 토글 기능 toggleEdit = () => { const { editing } = this.state; this.setState({ editing: !editing }); }; // select와 input 태그의 값이 변할 때 이벤트 처리 changeInput = event => { const { name, value } = event.target; this.setState({ [name]: value, date: getCurrentTimetoString() }); }; componentDidUpdate(prevProps, prevState) { const { data, onUpdate } = this.props; // 수정 버튼을 클릭한 경우(input 태그가 표시되게 해준다) if (!prevState.editing && this.state.editing) { this.setState({ type: data.type, price: data.price, usage: data.usage, date: data.date }); } // 적용 버튼을 클릭한 경우(App.js에 있는 update 함수를 호출) if (prevState.editing && !this.state.editing) { onUpdate(data.id, { type: this.state.type, price: this.state.price, usage: this.state.usage, date: this.state.date }); } } render() { const style = { border: "1px solid black", padding: "5px", margin: "5px" }; const { editing } = this.state; // 수정 if (editing) { return ( <div style={style}> <select value={this.state.type} name="type" onChange={this.changeInput} > <option>지출</option> <option>수입</option> </select> <input placeholder="금액" type="number" name="price" value={this.state.price} onChange={this.changeInput} /> <input placeholder="사용목적" name="usage" value={this.state.usage} onChange={this.changeInput} /> <button onClick={this.toggleEdit}>적용</button> <button onClick={this.remove}>삭제</button> </div> ); } // 일반 const { type, price, usage, date } = this.props.data; return ( <div style={style}> <div>{type}</div> <div>{toCommaString(price)}원</div> <div>{usage}</div> <div>{date}</div> <button onClick={this.toggleEdit}>수정</button> <button onClick={this.remove}>삭제</button> </div> ); } } export default AccountBookInfo; | cs |
수정 버튼을 추가하고 수정 버튼을 누르면 기존 div 태그가 select, input 태그로 바뀌어 내용을 수정할 수 있도록 합니다. 값의 변경이 발생하기 때문에 state를 정의하고 수정 버튼을 누른 유무를 확인하기 위해 editing 이라는 변수를 둡니다. 이 변수는 수정/젹용 버튼을 클릭될 때마다 toggleEdit 함수를 통해 토글됩니다(true->false, false->true). 그리고 AccountBookForm.js에서 select,와 input 태그의 값이 변경될 때마다 state를 변경하게 만들었던 함수인 changeInput을 똑같이 구현합니다. 마지막으로 componentDidUpdate API를 통해 수정/적용 버튼에 따른 결과처리를 해줍니다. 결과는?
다음과 같이 수정 작업을 해보면 정상적인 결과를 얻을 수 있습니다.
References
[Velopert 블로그 배열 다루기(2) 제거와 수정] https://velopert.com/3638
'프로그래밍 > React' 카테고리의 다른 글
[예제]간단한 가계부4 - 필터링과 최적화 (0) | 2019.02.12 |
---|---|
[예제]간단한 가계부2 - 배열관련 처리1 (0) | 2019.02.08 |
[예제]간단한 가계부1 - input 상태 관리 (0) | 2019.02.06 |
[문법]Life Cycle API (0) | 2019.02.04 |
[문법]props와 state (0) | 2019.01.31 |
- Total
- Today
- Yesterday
- 개발자
- 중간 연산
- #예제 #example #가계부 #Account Book
- #React #ReactJS #리액트
- 자바
- 토이 프로젝트
- java14
- #배열 #array #map 함수
- flatMapToLong
- Stream API
- 계획
- 충북 콕! 콕!
- Java8
- 목표
- flatMapToDouble
- lambda
- 람다
- flatMapToInt
- IntelliJ
- 변경사항
- jdk14
- java
- 익명 클래스
- modern java
- 회고
- flaMap
- mapToObj
- 스트림
- import문
- 다짐
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |