안 쓰던 블로그
React-컴포넌트 반복(map()과 key) 본문
HTML을 보면 반복되는 코드를 작성할 때가 있다
<ul>
<li>1번</li>
<li>2번</li>
<li>3번</li>
</ul>
이런 건 어떻게 효율적으로 바꿀 수 있을까? map()함수를 써봅시다
map()
맵은 파라미터로 전달된 함수로 배열 내 각 요소를 프로세싱하고 새로운 배열을 생성한다
문법
arr.map(callback, [thisArg])
callback: 새로운 배열의 요소를 생성한다
-currentValue: 현재 처리하고 있는 요소
-index: 현재 처리하고 있는 요소의 index값
-array: 현재 처리하고 있는 원본 배열
thisArg: callback함수 내부에서 사용할 this레퍼런스로 생략 가능하다
예제
배열 [1,2,3,4,5]의 각 요소를 제곱해서 새로운 배열을 만드는 예시
var numbers=[1,2,3,4,5];
var processed = numbers.map(function(num){return num*num;});
console.log(processed);
개발자 도구에서 실행시킨 결과
같은 내용을 ES6문법으로 작성한 코드
const numbers=[1,2,3,4,5];
const processed = numbers.map(num=>num*num);
console.log(processed);
var이 const가 되고 화살표 함수를 사용한다
데이터 배열을 컴포넌트 배열로 map하기
import React, { Component } from 'react';
class IterationSample extends Component {
render() {
const names=['봄', '가을', '겨울', '여름'];
const nameList=names.map((name)=>(<li>{name}</li>));
return (
<ul>
{nameList}
</ul>
);
}
}
export default IterationSample;
IterationSample.js를 새로 생성하고 위의 코드를 적는다
App.js에서 IterationSample 컴포넌트를 불러와 렌더링한다
잘 나오긴 한데, f12를 눌러보면 key가 없다고 한다
key가 뭘까? key에 대해서 알아봅시다
key
리액트에서는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었나 보려고 key를 쓴다
key가 없으면 DOM을 비교하는 중에 리스트를 하나씩 보면서 뭐가 바뀌었나 확인한다
key가 있으면 이 과정이 더 효율적으로 바뀐다
참고로 key값은 유일해야 한다
유일하지 않으면 렌더링하다가 오류가 날 것임
설정
key값은 map한수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 된다
import React, { Component } from 'react';
class IterationSample extends Component {
render() {
const names=['봄', '가을', '겨울', '여름'];
const nameList=names.map((name, index)=>(<li key={index}>{name}</li>));
return (
<ul>
{nameList}
</ul>
);
}
}
export default IterationSample;
index를 추가해서 key={index}로 key설정을 해주었다
이제 개발자 도구에서 key값이 없다는 에러를 내지 않는다
응용
데이터 삽입
import React, { Component } from 'react';
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 (
<div>
<input
onChange={this.handleChange}
value={this.state.name}/>
<button onClick={this.handleInsert}>추가</button>
<ul>{nameList}</ul>
</div>
);
}
}
export default IterationSample;
버튼을 눌러 추가할 수 있다
input값은 기본 값 공백 ''이 들어간다
ul위에 input이 들어가게 div로 크게 한 번 감싼다
handleChange와 input은 계속 같으니까 똑같이 해준다
중요한 건 handleInsert 메서드 처리방식인데, 기본 자바스크립트처럼 push가 아니라 state는 setState로 접근한다는 점을 기억해야 한다
push는 기존 배열 자체가 변형되므로 옳지 않은 사용이다
그래서 기존 배열을 사용하지 않고, 기존 배열+새 값을 합친 새 배열을 생성하도록 concat을 사용해서 리턴해준다
데이터 삭제
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>
)
);
...는 ES6문법 중 전개 연산자 라고 한다
전개 연산자는 ...뒤에 위치한 배열 값을 그대로 꺼내서 현재 배열에 복사하는 일을 한다
const numbers=[1,2,3];
const numbers2=[...numbers,4];
//[1,2,3,4]
이렇게 1,2,3을 꺼내서 현재 배열에 복사한 뒤 4를 붙이기 때문에 1,2,3,4가 나오는 식이다
그래서 위에 코드처럼 한다면, 일단 첫 번째 ... 때문에 slice로 배열의 0부터 inex까지의 수로 새 배열을 만든다
그리고 index+1부터 끝까지 새 배열을 만든다
이제 둘을 합치면 index만 뺀 새로운 배열이 만들어진다
아니면 배열 내장 함수 filter를 사용할 수도 있다
handleRemove=(index)=>{
const{names}=this.state;
this.setState({
names: names.filter((item,i)=>i!==index)
});
}
배열에서 특정 조건을 만족하는 값만 추출해서 새로운 배열을 만든다
여기서는 index번째를 제외한 원소만 있는 새 배열을 생성한다
아무튼 이제 렌더링하고 나면, 요소를 더블클릭하면 요소가 사라질 것이다
참고한 책: 리액트를 다루는 기술
'Web > React' 카테고리의 다른 글
React-함수형 컴포넌트 (0) | 2020.07.09 |
---|---|
React-컴포넌트 라이프사이클 메서드 (0) | 2020.07.07 |
React-ref (DOM에 이름 달기) (0) | 2020.07.07 |
React-이벤트 핸들링(onChange, onClick, input 여러 개, onKeyPress) (0) | 2020.07.06 |
React-컴포넌트(컴포넌트 생성, props, state) (0) | 2020.07.06 |