이롭게 현명하게
[React] 리액트 배열 렌더링하기 본문
목차
배열 렌더링
key의 존재 유무에 따른 업데이트 방식
[배열 렌더링]
다음과 같은 배열이 있다.
const users = [
{
id: 1,
username: 'uni',
email: 'uni@gmail.com'
},
{
id: 2,
username: 'dog',
email: 'dog@gmail.com'
},
{
id: 3,
username: 'cat',
email: 'cat@gmail.com'
}
];
<배열을 렌더링 하는 방법>
- 그대로 사용하기
- 컴포넌트 생성
- 동적 배열 사용시 map함수 사용
이 배열을 컴포넌트로 렌더링 한다면 어떻게 해야 할까?
<배열을 그대로 사용하여 렌더링>
import React from "react";
function UserList(){
const users =[
{
id : 1,
username : 'uni',
email : 'uni@gmail.com'
},
{
id : 2,
username : 'dog',
email : 'dog@gmail.com'
},
{
id : 3,
username : 'cat',
email : 'cat@gmail.com'
}
];
return(
<div>
<div>
<b>{users[0].username}</b> <span>{users[0].email}</span>
</div>
<div>
<b>{users[1].username}</b> <span>{users[1].email}</span>
</div>
<div>
<b>{users[2].username}</b> <span>{users[2].email}</span>
</div>
</div>
);
}
export default UserList;
그대로 사용한다면 같은 코드를 반복적으로 사용하기 때문에 비효율적이다.
만약 배열 길이가 고정적이라면 컴포넌트를 하나 더 생성하여 사용할 수 있다.
<컴포넌트를 하나 더 생성하여 사용>
import React from "react";
function User({user}){//props로 user를 받아온다.
return(
<div>
<b>{user.username}</b> <span>{user.email}</span>
</div>
);
}
function UserList(){
const users =[
{
id : 1,
username : 'uni',
email : 'uni@gmail.com'
},
{
id : 2,
username : 'dog',
email : 'dog@gmail.com'
},
{
id : 3,
username : 'cat',
email : 'cat@gmail.com'
}
];
return(
<div>
<User user={users[0]}/>
<User user={users[1]}/>
<User user={users[2]}/>
</div>
);
}
export default UserList;
배열이 고정적이지 않고 동적인 배열을 렌더링 하려면 자바스크립트 배열의 내장함수 map()을 사용해야 한다.
map() 함수는 배열 안에 있는 각 원소를 변환하여 새로운 배열을 만들어준다.
리액트에서 동적인 배열을 렌더링해야 할 때는 map 함수를 사용하여 일반 데이터 배열을 리액트 Element로 이루어진 배열로 변환해 준다.
<map함수 사용하기>
이 코드에서는 id가 고유 값이다.
import React from "react";
function User({user}){//props로 user를 받아온다.
return(
<div>
<b>{user.username}</b> <span>{user.email}</span>
</div>
);
}
function UserList(){
const users =[
{
id : 1,
username : 'uni',
email : 'uni@gmail.com'
},
{
id : 2,
username : 'dog',
email : 'dog@gmail.com'
},
{
id : 3,
username : 'cat',
email : 'cat@gmail.com'
}
];
return(
<div>
{
users.map(
user =>(<User user={user}/>)
)
}
</div>
);
}
export default UserList;
UserList.js:31 Warning: Each child in a list should have a unique "key" prop.
경고 메시지가 뜨는 이유 : 각 고유 원소에 key가 있어야만 배열이 업데이트될 때 효율적으로 렌더링 될 수 있다.
리액트에서 배열을 렌더링할 때는 key라는 props를 설정해야 한다.
key 값은 각 원소들마다 가지고 있는 고유 값으로 설정해야 한다.
return(
<div>
{
users.map(
user =>(<User user={user} key={user.id}/>)
)
}
</div>
);
만약 배열 안의 원소가 가지고 있는 고유한 값이 없다면 map() 함수를 사용할 때 설정하는 콜백함수의 두 번째 파라미터 index를 key로 사용하면 안 된다.
만약에 배열을 렌더링할 때 key 설정을 하지 않게 된다면 기본적으로 배열의 index 값을 key로 사용하게 되고, 경고 메시지가 뜬다.
[key의 존재 유무에 따른 업데이트 방식]
map에 key 값이 없다면 중간의 값이 바뀌었을 때 그 하윗값들이 전부 변하기 때문이다.
key 값을 사용한다면 key를 이용해 중간의 값을 추가하게 된다.
<key가 없을 경우>
다음과 같은 배열 array가 있다.
배열 array를 Element들로 변환하면 다음과 같은 결과가 나온다.
array.map(item => <div>{item}</div>);
이때 array 배열에 b와 c 사이에 x를 삽입한다.
배열에 x가 삽입된다면 당연히 새로운 div 태그가 삽입될 것으로 생각한다.
하지만 그렇지 않다.
<div> b </div> 와 <div> c </div> 사이에 새로운 태그가 생기는 것이 아닌 기존의 c가 z로 바뀌고 d는 c로, 맨 마지막에 d가 새로 삽입된다.
<div> c </div> 가 <div> x </div>로 바뀐다.
<div> d </div> 가 <div> c </div>로 바뀐다.
마지막으로 새로운 d가 생겨난다.
만약 배열 array에서 a를 삭제한다면 <div>a</div>만 없어지고 나머지는 그대로 있을 거라고 생각한다.
하지만 그렇지 않다.
<div>a</div>가 <div>b</div>로 바뀐다.
b가 x로 바뀐다.
x는 c로 바뀐다.
c는 d로 바뀐다.
마지막에 는 d가 없어진다.
키 값이 없다면 이러한 비효율적인 과정을 거치게 된다.
각 배열의 원소가 정확히 어떤 것을 렌더링 하고 있는지를 잘 모르기 때문이다.
단순히 자신이 n번째 원소인것만 알고 정확히 어떤 값을 렌더링 해야 하는지 모른다.
b가 삭제된다면 삭제되는것이 아닌 b가 x로 바뀌었다고 인식하게 된다.
<key가 있을 경우>
하지만 키가 있다면 달라진다.
고유 값이 있는 객체들이 있다. 이 고유 값을 key로 설정하게 되면 각 렌더링 한 결과물에서 정확히 어떤 객체를 가리키고 있는지 잘 알고 있다.
[
{id:0, text:’a’},
{id:1, text:’b’},
{id:2, text:’c’},
{id:3, text:’d’},
]
만약 {id:5,text:'x'}가 추가된다면 매우 효율적으로 업데이트된다.
b와 c 사이에 수정되지 않는 기존의 값은 그대로 두고 원하는 곳에 내용을 삽입할 수 있다.
삭제 또한 마찬가지이다.
<정리>
- 배열을 렌더링 하게 된다면 key를 설정해야 효율적으로 렌더링을 할 수 있다.
- 고윳값이 없는 경우에 key라는 자리에 index값을 넣을 수 있긴 하지만 그것은 비효율적이다.
- 다만 데이터가 몇 개 없을 경우, 자주 업데이트 되지 않는 경우 값을 index를 사용해도 문제가 되지는 않는다.
- 배열 안의 값이 자주 업데이트되는데 key를 index로 사용하면 매우 비효율적으로 업데이트된다.
잘못된 정보는 댓글에 남겨주시면 감사하겠습니다!😊
댓글과 좋아요는 큰 힘이 됩니다!
'웹 개발 > React' 카테고리의 다른 글
[React] 리액트 배열에 항목 추가하기 (2) | 2023.12.29 |
---|---|
[React] 리액트 useRef로 특정 DOM 선택하기 / 리액트 DOM 접근하기 (0) | 2023.12.28 |
[React] 리액트 사용자 입력 / input 상태 관리 (2) | 2023.12.26 |
[React] 리액트 useState (0) | 2023.12.22 |
[React] 리액트 조건부 렌더링 (1) | 2023.12.21 |