이번 장에서는 반복되는 코드를 효율적으로 보여주고 관리하는 방법에 대해 배워보겠습니다.
자바스크립트에서는 배열을 다룰 수 있는 유용한 내장 함수들이 있습니다.
forEach
: 배열의 각 요소들에게 일관된 작업을 수행할 수 있습니다.
사용법 - 배열명.forEach(파라미터)
map
: 배열 안의 모든 원소를 변환할 때 사용됩니다.
사용법 - 배열명.map(파라미터)
filter
: 배열에서 특정 조건을 만족하는 값들을 분류하여 새 배열을 만듭니다.
사용법 - 배열명.filter(파라미터)
push
: 배열의 맨 뒷부분에 요소를 추가합니다.
사용법 - 배열명.push(파라미터)
pop
: 배열의 맨 뒤 요소 하나를 반환하고 제거합니다.
사용법 - 배열명.pop()
concat
: 여러 개의 배열을 합친 새 배열을 만듭니다.
사용법 - 배열명.concat(파라미터)
더 자세한 내용은 아래 링크를 통해 확인할 수 있습니다.
https://learnjs.vlpt.us/basics/09-array-functions.html
반복되는 컴포넌트를 렌더링 하기 위해 자바스크립트 배열의 내장 함수 중 map() 함수를 이용합니다.
arr.map(callback, [thisArg]) 형태로 사용할 수 있습니다.
callback 함수는 새로운 배열의 요소를 생성하는 함수로, 파라미터로 currentValue(현재 처리하고 있는 요소), index(현재 처리하고 있는 요소의 index 값), array(현재 처리하고 있는 원본 배열)를 가집니다.
thisArg는 callback함수 내부에서 사용할 this 레퍼런스로 생략할 수 있습니다.
위와 같이 콘솔창을 열어 map() 함수를 작성해보세요. 배열 numbers의 각 요소의 제곱 값을 새로운 배열에 저장했습니다. 이처럼 map() 함수는 배열의 각 요소에 쉽게 접근할 수 있습니다.
map() 함수로 데이터 배열을 컴포넌트 배열로 변환할 수 있습니다. 예시로 문자열로 구성된 배열을 살펴보도록 하겠습니다.
import React from 'react';
const IterationSample = () => {
const names = ['눈사람', '얼음', '눈', '바람'];
const nameList = names.map(name => <li>{name}</li>);
return <ul>{nameList}</ul>;
};
export default IterationSample;
map() 함수를 이용하여 배열 names의 각 요소를 목록 형태인 배열을 만들었습니다. 이것을 App 컴포넌트에서 렌더링 하면 다음과 같은 결과를 볼 수 있습니다.
map() 함수를 이용해 JSX를 작성할 때는 위 예제처럼 DOM 요소를 작성해도 되고, 컴포넌트를 사용해도 됩니다.
하지만 개발자 도구의 콘솔 창에는 key가 없다는 경고 메시지가 뜨게 됩니다
리액트에서 key란 컴포넌트 배열을 렌더링 했을 때, 어떤 원소에 변동이 있었는지 알아내는 값입니다. key값은 언제나 유일해야 합니다. nameList에 key값을 설정하기 위해 아래와 같이 수정해봅시다.
import React from 'react';
const IterationSample = () => {
const names = ['눈사람', '얼음', '눈', '바람'];
const namesList = names.map((name, index) => <li key={index}>{name}</li>);
return <ul>{namesList}</ul>;
};
export default IterationSample;
이 예시에서는 반복하는 배열이 고유한 번호를 가지고 있지 않았기 때문에, 배열 names의 index를 이용하였습니다. 하지만 이러한 방법은 배열이 변경될 때 효율적이지 못하다는 단점이 있습니다.
그럼 이제 key값을 효율적으로 관리하고, 더불어 동적인 배열을 렌더링 하는 예시를 만들어보겠습니다. 동적으로 렌더링 하기 위해 useState를 이용하여 상태를 설정합니다.
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 namesList = names.map(name => <li key={name.id}>{name.text}</li>);
return <ul>{namesList}</ul>;
};
export default IterationSample;
useState를 세 번 사용했는데, 순서대로 데이터 배열, 텍스트를 입력할 input 상태, 고유 id입니다. 이제 고유 id를 이용하여 index대신 key값을 설정합니다.
데이터 추가 기능 구현하기
입력창에서 문자열을 입력받아 버튼을 누르면 배열에 추가되는 기능을 만들겠습니다.
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(“); // inputText를 비운다.
};
const namesList = names.map(name => <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange} />
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>
</>
);
};
export default IterationSample;
입력창에 문자열을 입력하면 onChange가 호출되고, inputText의 세터 함수를 이용해 inputText에 새로운 값을 넣어줍니다.
입력 후, 버튼을 누르면 onClick 함수가 호출됩니다. onClick 함수에서는 names 배열의 사본을 만들어 concat으로 새 데이터를 추가합니다. 그 후 세터 함수를 이용해 nextId와 배열 names를 업데이트합니다..
코드를 작성했다면 다음과 같은 브라우저 화면을 볼 수 있습니다
새 데이터를 추가할 때, push가 아닌 concat을 사용한 이유는 불변성 유지를 위해서입니다. 기존 상태를 그대로 두면서 새로운 값을 상태로 설정해야 나중에 리액트 컴포넌트의 성능을 최적화할 수 있습니다.
데이터 제거 기능 구현하기
항목을 더블클릭하면, 그 항목이 화면에 나타나지 않는 기능을 만들겠습니다.
불변성을 유지하기 위해 filter라는 함수를 이용할 것입니다. filter 함수는 특정 조건을 만족시키는 원소들만 분류하는 함수입니다.
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(“); // inputText를 비운다.
};
const onRemove = id => {
const nextNames = names.filter(name => name.id != = id);
setNames(nextNames);
};
const namesList = names.map(name => (
<li key={name.id} onDoubleClick={() => onRemove(name.id)}>
{name.text}
</li>
));
return (
<>
<input value={inputText} onChange={onChange} />
<button onClick={onClick}>추가</button>
<ul>{namesList}</ul>
</>
);
};
export default IterationSample;
namesList에서 항목을 더블 클릭 이벤트가 발생하면 onRemove 함수를 호출합니다.
onRemove는 이벤트가 발생된 요소의 id를 전달받아, 그 id를 가지지 않은 요소만 분류하여 names의 사본을 만듭니다. 이 사본이 세터 함수 전달되어 배열 names가 업데이트됩니다.
코드를 작성하였다면 다음과 같이 항목을 제거할 수 있습니다.
1) 자바스크립트 배열의 내장 함수 중 ( A ) 함수는 배열 안의 모든 원소를 변환할 때 사용되고, ( B ) 함수는 배열에서 특정 조건을 만족하는 값들을 분류하여 새 배열을 만든다.
2) key는 컴포넌트 배열을 렌더링 했을 때 ( C ) 위해 사용한다.
3) key값은 ( D ) 해야 한다.
4) 리액트에서 상태를 업데이트할 때 기존 상태를 그대로 두면서 새로운 값을 상태로 설정하는 것을 ( E )라고 부른다.
5) map 함수를 이용하기 위한 문법은 arr.map( F, G )이다. F는 새로운 배열의 요소를 생성하는 함수이고, G는 생략 가능하다.
6) 배열의 index를 key로 사용하면 ( H )하다.
7) 불변성을 유지하기 위해 배열에 새로운 항목을 추가할 때 ( I ) 함수를 사용한다.
8) 코너의 스터디 팀명을 담은 배열을 만들고, map 함수를 이용해 브라우저에 렌더링 하세요..
9) 자바스크립트로 일정 관리를 해봅시다. 할 일을 입력받아 브라우저에 띄우는 코드를 작성하세요. 이때, 입력창에 Enter을 입력하면 새 항목이 추가될 수 있도록 하세요.
Corner React1
Editor: 이조
[리엑트 스타터1] 8장. Hooks (0) | 2022.11.24 |
---|---|
[리엑트 스타터1] 7장. 컴포넌트의 라이프 사이클 메서드 (0) | 2022.11.17 |
[리액트 스타터 1] 5장. ref (0) | 2022.11.05 |
[리액트 스타터1] 4장. 이벤트 핸들링 (0) | 2022.10.13 |
[리액트 스타터 1] 3장. 컴포넌트 (0) | 2022.10.06 |