일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 출처 : https://joshua1988.github.io/web-development/javascript/promise-for-beginners/
- https://velog.io/@velopert/create-typescript-react-component
- 게시판
- http://jeonghwan-kim.github.io/dev/2019/06/25/react-ts.html
- toString
- 출처 : https://webdir.tistory.com/506
- object
- Today
- Total
Back Ground
React - 컴포넌트 반복 본문
IterationSample.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import React, { Component } from 'react'; class IterationSample extends Component{ render(){ return( <ul> <li>눈사람</li> <li>얼음</li> <li>눈</li> <li>바람</li> </ul> ); } } export default IterationSample; | cs |
이런식으로 <li>...</li>를 연속으로 사용 해야 할때 반복 코드를 이용해서 작성해보도록 하겠다
자바스크립트 배열의 map() 함수
자바스크립트 배열 객체의 내장 함수인 map함수를 사용하여 반복되는 컴포넌트를 랜더링할 수 있다.
map 함수는 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 프로세싱한 후 그 결과로 새로운 배열 생성한다.
1 | var new_array = arr.map(function callback(currentValue[, index[, array]]) { // new_array의 새 요소 반환 }[, thisArg]) | cs |
arr.map( callback() , [thisArg] ) |
map의 callback은 새로운 배열의 요소를 생성하는 함수가 있는데
- currentValue : 현재 처리하고 있는 요소
- index : 현재 처리하고 있는 요소의 index값
- array : 현재 처리하고 있는 원본 배열
map의 thisArg은 (선택항목) callback 함수 내부에서 사용할 this 레퍼런스
출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map
map 함수 사용 예
map함수를 사용하여 배열 [ 1, 2 , 3 , 4, 5 ]의 각 요소를 제곱해서 새로운 배열을 생성해 보자
1 2 3 4 5 6 7 | var numbers = [1,2,3,4,5]; var processed = numbers.map(function(num){ return num * num; }); console.log(processed); | cs |
그러면 배열 순서대로 num에 배열 값이 들어간다.
결과를 보면
[ 1*1, 2*2, 3*3, 4*4, 5*5 ] 가 연산처리 된
[ 1, 4, 9, 16, 25] 가 나오게 된다.
데이터 배열을 컴포넌트 배열로 map 하기
IterationSample.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import React, { Component,Fragment } from 'react' export default class IterationSample extends Component { render() { const names =['눈사람','얼음','눈','바람']; const nameList = names.map( (name) => ( <li>{name}</li> ) ); console.log(nameList); return ( <ul> {nameList} </ul> ) } } | cs |
<li></li>의 JSX코드로 된 배열을 생성 한 후 nameList에 담는다
JSX는 { <li></li> } 가 아닌 (<li><li>)에 담아야한다.
참고 : http://backback.tistory.com/296
후에 App.js 에 컴포넌트를 불러오게 되면
DOM에는 전혀 문제없어보이지만 개발자도구에보면
'key' prop이 없다고 경고 메시지가 나오게 된다.
Key
리액트에서 key는 컴포넌트 배열을 랜더링했을 때 어떤 원소에 변동이 있는지 알아내기 위해 사용.
key가 없을 때는 가상 DOM을 비교하는 과정에서 리스트를 순차적으로 비교 하여 변화를 감지해야 하는데
key가 있을 때는 이 값을 사용하여 어떤 변화가 일어났는지 더욱 빠르게 알아 낼수 있다.
key설정
key값을 설정할 떄는 map함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯하면 된다.
당연 key값은 유일해야 한다.
사용 예)
1 2 3 4 5 6 7 | const articleList = articles.map(article => ( <Article title={articles.title} writer={articles.writer} key={articles.id} /> ); | cs |
그러면 아까 전의 예제를 응용 해보자
IterationSample.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import React, { Component,Fragment } from 'react' export default class IterationSample extends Component { render() { const names =['눈사람','얼음','눈','바람']; const nameList = names.map( (name,index) => ( <li key={index}>{name} </li>) ); console.log(nameList); return ( <ul> {nameList} </ul> ) } } | cs |
그러면 배열을 state에 초기 데이터 담아서 응용 해보자
IterationSample.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import React, { Component,Fragment } from 'react' export default class IterationSample extends Component { state = { names : ['눈사람','얼음','눈','바람'], } render() { const nameList = this.state.names.map( (name,index) => (<li key={index}>{name}</li>) ); return ( <ul> {nameList} </ul> ) } } | cs |
데이터 추가 기능
state names의 배열에 데이터를 추가하는 기능을 만들어보자
IterationSample.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 | import React, { Component,Fragment } from 'react' export default class IterationSample extends Component { state = { names : ['눈사람','얼음','눈','바람'], name : '', } handleChange = (e) =>{ this.setState({ name : e.target.value }); } handleInsert = () =>{ this.setState({ names : this.state.names.concat(this.state.name), name:'', }); } render() { const nameList = this.state.names.map( (name,index) => (<li key={index}>{name}</li>) ); return ( <Fragment> <br/><br/> <input onChange={this.handleChange} value={this.state.name} /> <button onClick={this.handleInsert}>추가</button> <ul> {nameList} </ul> </Fragment> ) } } | cs |
input값은 기본 값이 공백으로 state에 저장했고,
input과 button에서 필요한 이벤트 핸들러 메서드를 준비하여 각 요소에 이벤트를 설정
1 2 3 4 5 6 | handleInsert = () =>{ this.setState({ names : this.state.names.concat(this.state.name), name:'', }); } | cs |
이 메소드에서 데이터를 추가하는 방식으로 하는 이유는
기존의 자바스크립트에서는 this.state.names.push('...')로 배열을 수정해도 되지 않나 싶은데
state는 언제나 setState메서드로 업데이트해야 하고 직접 접근하여 수정하면 안된다 !
그렇기 때문에 push같은 함수를 쓴다면 기존 배열 자체가 변형되므로 이는 잘못된 사용이다
( 자동으로 리렌더링을 트리거하지 않기 때문 )
여기선 기존 배열과 새 값을 합치는 concat을 이용하여 사용하면 오류없이 작동한다.
데이터 제거 기능
더블 클릭 이벤트 발생 시 데이터를 지워보겠다.
IterationSample.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 | import React, { Component,Fragment } from 'react' export default class IterationSample extends Component { state = { names : ['눈사람','얼음','눈','바람'], name : '', } handleChange = (e) =>{ this.setState({ name : e.target.value }); } handleInsert = () =>{ this.setState({ names : this.state.names.concat(this.state.name), name:'', }); } handleRemove = (index) =>{ const {names} = this.state; this.setState({ names: [ ...names.slice(0,index), ...names.slice(index + 1, names.length), ] }); } render() { const nameList = this.state.names.map( (name,index) => ( <li key={index} onDoubleClick={() => this.handleRemove(index)} > {name}</li> ) ); return ( <Fragment> <br/><br/> <input onChange={this.handleChange} value={this.state.name} /> <button onClick={this.handleInsert}>추가</button> <ul> {nameList} </ul> </Fragment> ) } } | cs |
여기 지우는 이벤트 메소드에서 보면
1 2 3 4 5 6 7 8 9 10 | handleRemove = (index) =>{ const {names} = this.state; this.setState({ names: [ ...names.slice(0,index), ...names.slice(index + 1, names.length), ] }); } | cs |
일단
1 | const {names} = this.state; | cs |
이 부분이 익숙하지 않을 수 있으니 ES5 방식으로 하자면
1 | var names = this.state.names; | cs |
1 2 3 4 | names: [ ...names.slice(0,index), ...names.slice(index + 1, names.length), ] | cs |
arr.slice(begin, end) |
slice( 시작 index 부터 , 끝 index 전까지)
ES5 방식
1 2 | const numbers = [1,2,3,4,5]; const moreNumbers = [ ...numbers, 6 ]; //[1,2,3,4,5,6] | cs |
참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
코드에서는
.slice(0,index)
0부터 선택한 index전까지 원소들을 가진 새 배열을 만든다.
여기에서 전개 연사자를 사용한 이유는 소스 코드의 간결함과 가독성 때문이다
전개연사자를 사용하지 않았다면 slice한 배열을 concat했어야 하는데 그러면 코드가 너무 길다.
ES5 방식
1 2 3 | this.state.names.slice(0,index).concat( this.state.names.slice(index+1, this.state.names.length) ) | cs |
동작
예 ) names = [ 0, 1, 2, 3, 4, 5, 6 ] .slice( 0 , index) // index = 4 => [0,1,2,3] .slice(index + 1 , this.state.names.length) (5 , 7) => [0,1,2,3] + [ 5,6 ] = [0,1,2,3,5,6] |
전개 연산자를 쓰면 저렇게 간결하게 바뀌게 된다.
삭제 함수를 더 간단하게 작성하고 싶다면
filter를 사용한다.
IterationSample.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 | import React, { Component,Fragment } from 'react' export default class IterationSample extends Component { state = { names : ['눈사람','얼음','눈','바람'], name : '', } handleChange = (e) =>{ this.setState({ name : e.target.value }); } handleInsert = () =>{ this.setState({ names : this.state.names.concat(this.state.name), name:'', }); } handleRemove = (index) =>{ const {names} = this.state; /* this.setState({ names: [ //ES6 전개 연산자 // ...names.slice(0,index), // ...names.slice(index + 1, names.length), //ES5 // this.state.names.slice(0,index).concat( // this.state.names.slice(index+1, this.state.names.length) // ) ] }); */ // 필터링 this.setState({ //filter로 index번째를 제외한 원소만 있는 새 배열 생성 names: names.filter( (item, i)=> i !== index ) }); } render() { const nameList = this.state.names.map( (name,index) => ( <li key={index} onDoubleClick={() => this.handleRemove(index)} > {name}</li> ) ); return ( <Fragment> <br/><br/> <input onChange={this.handleChange} value={this.state.name} /> <button onClick={this.handleInsert}>추가</button> <ul> {nameList} </ul> </Fragment> ) } } | cs |
'Javascript > React.js' 카테고리의 다른 글
React - 함수형 컴포넌트 (0) | 2018.11.01 |
---|---|
React - 라이프 사이클 (1) | 2018.10.31 |
React - ( <mark up> ) 표현 (0) | 2018.10.27 |
React - ref : DOM에 이름 달기 (0) | 2018.10.20 |
React - 이벤트 핸들링 (0) | 2018.10.20 |