5. 컴포넌트 반복 (map, key)

나혜수·2023년 3월 14일
0

리액트

목록 보기
5/23

자바스크립트 배열의 map( ) 함수

배열 객체의 내장 함수인 map을 사용해 반복되는 컴포넌트를 렌더링할 수 있다.

// 새로운 배열 반환
arr.map(callback, [thisArg])

arr.map((currentValue, index, array) => { ... })
  • callback
    - currentValue : 현재 처리 중인 요소
    - index : 현재 처리 중인 요소의 인덱스
    - array : 현재 처리 중인 원본 배열

  • [thisArg]
    callback 함수 내부에서 사용할 this 레퍼런스

🐣 예시

var numbers = [1,2,3,4,5]

const result = numbers.map(num=> {
	return num * num
})

console.log(result) // [1,4,9,16,25]

key

import React from "react";

const IterationSample = () =>{
    const names = ['a','b','c','d']
    const nameList = names.map(name => <li>{name}</li>)
    return <ul>{nameList}</ul>
}

export default IterationSample

위와 같은 배열의 b와 c 사이에 z를 삽입하게 되면, 리렌더링을 하는 경우 b와 c 사이에 새로운 div 태그를 삽입하는 것이 아니라 기존의 c → z, d → c로 바뀐 후 맨 마지막에 d가 새롭게 삽입된다. 즉, 새롭게 추가된 부분 이하 배열 요소에 전부 영향을 준다.
이후 [a, b, z, c, d] 에서 a를 제거하면, 기존의 a → b, b → c, z → c, c → d로 바뀌며 맨 마지막에 있는 d는 제거된다. 배열 요소의 삭제도 변경된 배열 요소 이하 배열 요소에 모두 영향을 끼친다.

즉 key가 없는 경우, virtual DOM을 비교하는 과정에서 변경이 필요하지 않은 배열의 요소까지 변경이 일어나게 되므로 비효율적이다. 이런 부분을 개선하기 위해서 key를 사용한다.

key 설정

import React from "react";

const IterationSample = () =>{
    const names = ['a','b','c','d']
    const nameList = names.map((name, index) => <li key={index}>{name}</li>)
    return <ul>{nameList}</ul>
}

export default IterationSample

❗고유한 값이 없을 때만 index 값을 key로 사용해야 한다. index를 key로 사용하면 배열이 변경될 때 효율적으로 리렌더링하지 못한다.


동적인 배열 렌더링

IterationSample.js

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 = (e) => {
        const nextNames = [...names, {id:nextId, text:inputText}]
        setNames(nextNames)
        setNextId(nextId + 1)
        setInputText('')
    }

    const onKeyUp = (e) =>{
        if(e.key === 'Enter'){
            onClick()
        }
    }

    // 각 항목 더블클릭 시 데이터 제거 기능 
    const onRemove = (id) => {
        const nextNames = names.filter(name => 
            id !== name.id
        )
        setNames(nextNames)

    }

    const nameList = names.map( name => {
        return <li 
      	key={name.id}  
      	onDoubleClick={() => onRemove(name.id)}>{name.text}</li>
    })
    // onDoubleClick={onRemove(name.id)} 이렇게 쓰면 안됨
    // 이벤트에서 실행할 자바스크립트 코드는 함수 형태로 전달해야 한다. 

    return (
        <>
        <input value={inputText} onChange={onChange} onKeyUp={onKeyUp} />
        <button onClick={onClick}>추가</button>
        <ul>{nameList}</ul>
        </>
    )       
}

export default IterationSample

profile
오늘도 신나개 🐶

0개의 댓글