TIL 22 | Array.prototype.map() , key props

Soojeong Lee·2021년 6월 27일
0

react

목록 보기
6/7
post-thumbnail

Array.prototype.map()

✏️ React를 통해서 JSX를 사용할 때, 자주 사용되는 Javascript 문법인 Array.map에 대하여 공부하기 위해서 쓰는 글! Array.map()

1.Array.map()

정의

메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.

map

1️⃣ callback 함수를 각각의 요소에 대해 한번씩 순서대로 불러 그 함수의 반환값으로 새로운 배열을 만든다.

2️⃣ callback 함수는 (undefined도 포함해서) 배열 값이 들어있는 인덱스에 대해서만 호출됩니다. 즉, 값이 삭제되거나 아직 값이 할당/정의되지 않은 인덱스에 대해서는 호출되지 않는다.
➡️ map을 호출한 배열의 중간이 비어있는 경우, 결과 배열 또한 동일한 인덱스를 빈 값으로 유지한다.

3️⃣ map은 호출한 배열의 값을 변형하지 않습니다. 단, callback 함수에 의해서 변형될 수 있다.

4️⃣ map이 처리할 요소의 범위는 첫 callback을 호출하기 전에 정해진다.
➡️ 즉, map이 시작한 이후 배열에 추가되는 요소들은 callback을 호출하지 않는다.
➡️ 배열에 존재하는 요소들의 값이 바뀐 경우 map이 실행되는 시점의 값이 callback에 전달된다. map이 시작되고, 실행되기 전에 삭제된 요소들은 실행되지 않는다.

✔️ Array.map()은 각각의 Index에 함수를 실행시키는 것이다.
즉, 1, 4, 9, 16에 각각 x => x * 2의 함수를 반영 시키는 것이다.

🔑 기존 배열의 값을 변경하는 것이 아닌 새로운 배열을 반환하는 것이 다른 메서드와 차이점인 것 같다.

문법

arr.map(callback(currentValue[, index[, array]])[, thisArg])

매개변수

✔️ callback : 새로운 배열 요소를 생성하는 함수(화살표 함수). callback 함수는 호출될 때 대상 요소의 값, 그 요소의 인덱스, 그리고 map을 호출한 원본 배열 3개의 인수를 전달 ( 🍯 공식 문서에서 []는 optional ! )

  • currentValue : 처리할 현재 요소.
    ➡️ index : 처리할 현재 요소의 인덱스. Optional
    ➡️ array : map()을 호출한 배열. Optional

  • thisArg : callback을 실행할 때 this로 사용되는 값. Optional
    ➡️ thisArg 매개변수가 map에 전달된 경우 callback 함수의 this값으로 사용됩니다.
    ➡️ 그 외의 경우 undefined값이 this 값으로 사용됩니다.
    ➡️ callback 함수에서 최종적으로 볼 수 있는 this 값은 함수 내 this를 정하는 일반적인 규칙에 따라 결정됩니다.

✔️ return : 배열의 각 요소에 대해 실행한 callback의 결과를 모은 새로운 배열.

2. map 함수 적용시 key props를 부여하는 이유

  1. React 공식문서를 참조하였습니다.

  2. 직접 작성한 코드와 공식문서를 비교하며 이해하였습니다.

먼저, React에서 배열을 element 리스트로 만드는 방식은 Javscript에서 list를 변환하는 방식과 비슷하다는 것을 참고하자!

1. 여러개의 컴포넌트 렌더링 하기

1️⃣ map() 함수를 사용하여 numbers라고 정의된 배열을 반복해서 실행한다.
2️⃣ listItems 에 map() 함수는 각 항목에 대해 <li>를 반환하고, 그 배열을 저장한다.
3️⃣ listItems 배열을 <ul>엘리먼트 안에 포함하고 DOM에 렌더링 한다.

2. 기본 리스트 컴포넌트

: 컴포넌트 안에서 리스트를 렌더링 한다.

위에서 실행한 numbers 배열을 받아 li를 출력하는 컴포넌트로 리팩토링 할 수 있다.

❗️ 이렇게 코드를 실행하면 list의 각 항목에 key를 넣어야 한다는 경고가 뜬다.
❗️ 그 이유는, "key"는 list를 만들 때 포함해야하는 특수한 문자열 attribute이기 때문이다.
❗️ numbers.map() 안에서 리스트의 각 항목에 key를 할당하면 문제가 일차적으로 해결된다.

3. key 🔑

✔️ key 의 역할

  • React가 어떤 항목을 변경, 추가, 삭제할지 식별하는 것을 돕는다.
  • li에 고유성을 부여하기 위해 배열 내부에 지정해야 한다.

✔️ key를 선택하는 방법

  • li의 다른 항목 사이에서 해당 항목을 고유하게 식별할 수 있는 문자열을 사용하는 것이 좋다.
  • 따라서 대부분의 경우 데이터의 ID를 key로 사용한다.
  • 만일, ID가 없다면 최후의 수단으로 index를 key로 사용할 수 있다.
    ➡️ 하지만, 항목의 순서가 바뀌는 경우 index를 사용하는 것은 권장 사항이 아니다. 왜냐하면 이로 인해 성능저하, 컴포넌트의 state의 문제가 발생할 수 있기 때문이다.
  • 즉, key는 반드시 변하지않고, 예상가능하며, 유일해야하는 속성을 가진다.

4. key로 컴포넌트 추출하기

: key는 주변 배열의 context에서 의미가 있다.
❗️ 즉, ListItem 컴포넌트를 추출한 경우, ListItem 안에 있는 <li>가 아닌 배열인 <ListItem/>가 key 값을 가진다.
❗️ 공식 문서에서는 map() 함수 내부의 엘리먼트에 key 값을 넣어주는 것을 추천한다.
❗️ map() 함수가 너무 중첩된다면 컴포넌트로 추출하는 것이 맞다.

3. 나의 코드 👩🏻‍💻

1. 메인 컴포넌트

<ul id="commnetBox">
  {this.state.commentList.map((commnetComponent, index) => {
    return <Commnet value={commnetComponent} key={index} />;
  })}
</ul>

➡️ state로 댓글 구현하는 기능은 이전 과제에서 만들어 두었기 때문에, 이를 컴포넌트화하는 과정이 주된 과제였다. map() 함수 내부에 key값을 넣어주어야하는 것이 좋다고 하여 ul태그 안에 직접 map() 함수를 적용하여 key값을 주었다.
➡️ 여기서 궁금한 점은 <ul> 태그안에 작성한 map() 함수를 state 값을 담아둔 함수들과 묶어서 관리할 수 없을까 ? 하는 생각이 들었다..! 혹 더 효율적인 방법이 있는지 알아보아야겠다.

2. 댓글 컴포넌트

export class Commnet extends Component {
  render() {
    return (
      <div>
        <li>
          <Link className="commentUserId">eessoo__</Link>
          {this.props.value}
        </li>
      </div>
    );
  }
}

➡️ 공식문서에서 이야기 했던 것 처럼, 자식 컴포넌트엔 key를 지정할 필요가 없다.
➡️ 또한, 부모 컴포넌트에서 value값을 받아와야하기 때문에, props 개념을 사용하였다.

3. 느낀점

✏️ 리액트는 자바스크립트보다 직접 컴포넌트에 문법을 적용할 수 있어서 좋다..!
✏️ 하지만.. 생전 처음 들어보는 리액트는..지금 내가 구현하고도 잘 구현된 것인지 판단하기가 어려운 수준이다. 조금 더 심도 있게 코드를 복습하며 이론을 채워나가야겠다.
✏️ 부족하다고 느껴지는 코드를 공개하는건 참 용기가 필요한 일이지만 그렇지 않으면 발전하기가 어려우니, 코드를 쉐어하고 보여주면서 더 나은 코드를 위해 움직여야겠다.

profile
🍼 newbie frontend developer

0개의 댓글