[react] 컴포넌트 반복
by 너나나import React from 'react';
const IterationSample = () => {
return (
<ul>
<li>눈사람</li>
<li>얼음</li>
<li>눈</li>
<li>바람</li>
</ul>
)
};
export default IterationSample;
IterationSample.js 라는 파일을 작성했다!! 이 코드를 보면 <li> </li>이 형태가 계속 반복되는 것을 볼 수 있다.
지금은 li태그 하나뿐이라 괜찮은데 좀 더 코드가 복잡해지면 코드양도 늘어나고 파일 용량도 증가한다!! 그래서 이번에는 리액트 프로젝트에서 반복적인 내용을 효율적으로 보여주고 관리하는 방법을 알아보자!!!
자바스크립트 배열의 map() 함수
자바스크립트 배열 객체의 내장 함수인 map 함수를 사용하여 반복되는 커모넌트를 렌더링할 수 있다!!
map 함수는 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 그 결과로 새로운 배열을 생성한다!!!
var numbers = [1, 2, 3, 4, 5];
var processed = numbers.map(function(num){
return num*num;
});
console.log(processed);
이 친구를 실행하면 [1, 4, 9, 16, 25]가 나온다.
배열의 원소들이 제곱돼서 새로운 배열이 만들어진 것을 볼 수 있다!!
이 코드를 ES6 문법으로 작성해보면
const numbers = [1, 2, 3, 4, 5];
const result = numbers.map(num => num*num);
console.log(result);
이렇게 화살표 함수로 좀 더 간단하게 표현할 수 있다. 이제 이 친구를 활용해서 기존 배열을 이용해 컴포넌트에 구성된 배열을 생성해보자!!
아까 작성한 IterationSample.js를 수정하자!!
import React from 'react';
const IterationSample = () => {
const names = ['눈사람', '얼음', '눈', '바람'];
const nameList = names.map(names => <li>{names}</li>);
return <ul>{nameList}</ul>
};
export default IterationSample;
문자열로 구성된 배열을 선언했고 이 배열 값을 사용해서 <li></li> JSX 코드로 된 배열을 새로 생성한 후에 nameList에 담아줬다.
App에 IterationSample 컴포넌트를 불러와 렌더링하면 우리가 처음에 작성한 코드와 동일하게 실행된 것을 볼 수 있다!!
근데 사실 이 친구는 완벽하지 않다!! f12를 눌러서 개발자 도구를 확인해보면
이렇게 key prop가 없다고 경고 메세지로 소리지르고 있는게 보인다!!! key가 뭘까?!!?
리액트에서 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내려고 사용한다!! 데이터를 다룰 때 원소를 새로 생성, 제거, 수정할 수 있는데 key가 없을 때는 Virtual DOM을 비교하는 과정에서 리스트를 순차적으로 비교하면서 변화를 감지한다. 하지만 key가 있다면 이 값을 사용하여 어떤 변화가 일어났는지 더욱 빠르게 알아낼 수 있다!!
그래서 key 값을 설정할 때는 map 함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 된다. key 값은 언제나 유일해아하기 때문에 데이터가 가진 고윳값을 key값으로 설정해야 한다. 뭐 게시판의 게시글을 렌더링한다면 게시물 번호를 key값으로 설정하면 되겠지!!
하지만 우리가 만든 컴포넌트에는 고유번호가 없다!! 이럴때는 map 함수에 전달되는 함수의 인수인 index 값을 사용하면 된다!! 작성한 코드를 수정하자!!
import React from 'react';
const IterationSample = () => {
const names = ['눈사람', '얼음', '눈', '바람'];
const nameList = names.map((names,index) => <li key = {index}>{names}</li>);
return <ul>{nameList}</ul>
};
export default IterationSample;
이러고 실행된 프로젝트에 개발자도구를 켜서 확인해보면 warning이 사라진 것을 볼 수 있다!!! 와~~~
고유한 값이 없을 때만 index값을 key로 사용해야 한다!! index를 key로 사용하면 배열이 변경될 때 효율적으로 리렌더링하지 못한다고 한다!!
그러면 우리는 다시 위의 코드에 id라는 고윳값을 추가해주고, 데이터를 추가하는 기능을 구현해보자!!!
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{id: 1, text: '눈사람'},
{id: 2, text: '얼음'},
{id: 3, text: '눈'},
{id: 4, text: '바람'}
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const onChange = e => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId, // nextId 값을 id로 설정
text: inputText
});
setNextId(nextId+1); // nextId값에 1을 더해준다
setNames(nextNames); // names값을 업데이트
setInputText(''); // input값을 비움
};
const nameList = names.map((names,index) => <li key = {names.id}>{names.text}</li>);
return (
<>
<input value = {inputText} onChange = {onChange}/>
<button onClick={onClick}>추가</button>
<ul>{nameList}</ul>
</>
)
};
export default IterationSample;
여기서 배열에 새 항목을 추가할 때 배열의 push함수를 사용하지않고 concat함수를 사용했는데, push 함수는 기존 배열 자체를 변경해주고 concat은 새로운 배열을 만들어준다는 차이점이 있다!!
onClick 함수에서 새로운 항목을 추가할때 id 값은 nextId를 사용하게 하고, 클릭될 때마다 값이 1씩 올라간다.
그리고 button이 클릭될 때 기존의 input값을 비워줬다!!
이번에는 각 항목을 더블클릭하면 해당 항목이 사라지는 기능을 구현해보자!!
특정 항목을 지울 때는 배열의 내장 함수 filter을 사용한다. 이 filter함수를 사용하면 배열에서 특정 조건을 만족하는 원소들만 쉽게 분류할 수 있다!!
const numbers = [1, 2, 3, 4, 5, 6];
const biggerThanThree = numbers.filter(number => number > 3);
console.log(biggerThanThree)
이러면 [4, 5, 6]만 나온다!!
특정 원소를 제외시키고 싶다면
const numbers = [1, 2, 3, 4, 5, 6];
const withoutThree = numbers.filter(number => number !== 3)
console.log(withoutThree)
이렇게 사용하면 3을 제외함 [1, 2, 4, 5, 6]이 출력된다!! 이를 이용해서 항목 제거 기능을 구현해보자!!
import React, { useState } from 'react';
const IterationSample = () => {
const [names, setNames] = useState([
{id: 1, text: '눈사람'},
{id: 2, text: '얼음'},
{id: 3, text: '눈'},
{id: 4, text: '바람'}
]);
const [inputText, setInputText] = useState('');
const [nextId, setNextId] = useState(5); // 새로운 항목을 추가할 때 사용할 id
const onChange = e => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId, // nextId 값을 id로 설정
text: inputText
});
setNextId(nextId+1); // nextId값에 1을 더해준다
setNames(nextNames); // names값을 업데이트
setInputText(''); // input값을 비움
};
const onRemove = id => {
const nextNames = names.filter(name => name.id !== id);
setNames(nextNames);
}
const nameList = names.map((names,index) => <li key = {names.id} onDoubleClick={() => onRemove(names.id)}>{names.text}</li>);
return (
<>
<input value = {inputText} onChange = {onChange}/>
<button onClick={onClick}>추가</button>
<ul>{nameList}</ul>
</>
)
};
export default IterationSample;
이렇게 하고 브라우저에서 항목을 더블클릭하면 제거된다!!
참고 자료
누구든지 하는 리액트 1편: 리액트는 무엇인가 | VELOPERT.LOG
이 튜토리얼은 10편으로 이뤄진 시리즈입니다. 이전 / 다음 편을 확인하시려면 목차를 확인하세요. 프론트엔드 라이브러리 / 프레임워크 리액트는 정말 인기있는 프론트엔드 라이브러리입니다.
velopert.com
「리액트를 다루는 기술 - 김민준」
'study > react (2021 여름방학)' 카테고리의 다른 글
[react] Hooks (0) | 2021.07.26 |
---|---|
[react] 라이프사이클 메서드 (0) | 2021.07.24 |
[react] DOM에 이름 달기 ref (0) | 2021.07.17 |
[react] 이벤트 핸들링 (0) | 2021.07.17 |
[react] props, state (0) | 2021.07.13 |
블로그의 정보
공부 기록
너나나