티스토리 뷰

FrontEnd/React

6장. 컴포넌트 반복

맹정 2023. 3. 3. 23:44

# 어떻게 하면 효율적으로 보여주고 관리가 가능할까?

자바스크립트에는 배열 객체 내장 함수인 map() 함수를 사용하여, 반복되는 컴포넌트를 렌더링 할 수 있습니다. map 함수는 파라미터로 전달된 함수를 사용하여 배열 내 각 요소를 원하는 규칙에 따라 변환 뒤 그 결과로 새로운 배열을 생성합니다.

 

map() 함수의 문법
- arr.map(callback, [thisArg])

callback : 새로운 배열의 요소를 생성하는 함수로 파라미터는 세가지 입니다.

  1. currentValue : 현재 처리하고 있는 요소
  2. index : 현재 처리하고 있는 요소의 index 값
  3. array : 현재 처리하고 있는 원본 배열

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

# 데이터 배열을 컴포넌트 배열로 변환하기

const Iteration = () => {
	return(
    	<ul>
            <li>눈사람</li>
            <li>눈</li>
            <li>루돌프</li>
            <li>얼음</li>
        </ul>
    )
}
export default Iteration

코드에서 계속적으로 <li></li> 형태가 반복되는것을 발견할 수 있습니다.

코드가 방대해질수록 용량도 커지고, 관리 하기도 힘들어질겁니다.

const Iteration = () => {
    const names = ['눈사람','눈','루돌프','얼음']
    const nameList = names.map(name => <li>{name}</li>)
    return <ul>{nameList}</ul>
}
export default Iteration

문자열로 구성된 배열을 선언 후, <li></li> JSX 코드로 된 배열을 새로 생성 후 nameList 에 담습니다.

map 함수에서 JSX 작성 할 때는 DOM 요소를 작성해도 되고, 컴포넌트를 사용해도 됩니다.

 

이제 코드를 렌더링하면, 개발자 도구의 콘솔에서 다음과 같은 경고를 발견할 수 가 있습니다. 여기서 key 란 무엇일까요?

# key?

리액트에서 key는 컴포넌트 배열을 렌더링 했을때 어떤 원소에 변동이 있었는지 알아내려고 합니다. key가 없을 때는 virtualDOM 을 비교하는 과정에서 리스트를 순차적으로 비교하여 변화를 감지합니다. 하지만 key 가 있다면 어떤 변화가 있었는지 더욱 빠르게 알아내는게 가능합니다.

# key 설정

key 값을 설정할 때는 map 함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 됩니다. key 값은 언제나 유일 해야합니다.

 

const Iteration = () => {
    const names = ['눈사람','눈','루돌프','얼음']
    const nameList = names.map((name,index) => <li key = {index}>{name}</li>)
    return <ul>{nameList}</ul>
}
export default Iteration

<li> 에 map 함수에 전달되는 콜백 함수의 인수인 index 값을 사용합니다. 이제는 개발자 도구에서 더이상 경고 메세지를 표시 하지 않습니다. 고유한 값이 없을때만 index 값을 key 로 사용해야합니다. index를 key 로 사용하면 배열이 변경될때 효율적으로 리렌더링 할 수 없습니다. 

 

# key 응용

고정된 index 값을 key로 사용하면 리렌더링이 비효율적이라 배웠는데, 이러한 상황에서 어떻게 고윳값을 만들수 있는지 알아봅시다.

  1. 초기 상태 설정하기
  2. 데이터 추가 기능 구현하기
  3. 데이터 제거 기능 구현하기

1.  초기 상태 설정하기 

import {useState} from 'react'

const Iteration = () => {
	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)
    
    const nameList = nams.map(name => <li key={name.id}>{name.text}</li>)
    return <ul>{nameList}</ul>
}
export default Iteration

useState를 사용하여 상태를 설정해보록 하겠습니다. 세가지 상태를 사용할텐데, 하나는 데이터배열, 다른 하나는 텍스트를 입력하는 input 상태, 다른 하나는 데이터 배열에서 새로운 항목을 추가할때 사용하는 고유 id 입니다.

 

 

 

2.  데이터 추가 기능 구현하기

이제 새로운 이름을 등록 할 수있는 기능을 구현해봅시다.

 

import {useState} from 'react'

const Iteration = () => {
	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)
    
    const onChange = e => setInputText(e.target.value)
    const onClick = () => {
    	const nextNames = names.concat({
        	id : nextId,
            text : inputText
        })
        setNextId(nextId + 1)
        setNames(nextNames)
        setInputText('')
    }
    
    const nameList = nams.map(name => <li key={name.id}>{name.text}</li>)
    return 
    <>
    <input value = {inputText} onChange = {onChange}/>
    <button>추가</button>
    <ul>{nameList}</ul>
    </>
}
export default Iteration

배열에 새 항목을 추가 할때 push 를 사용하지않고 concat을 사용하였는데요. push 는 기존 배열 자체를 변경해주는 방면에, concat 은 새로운 배열을 만들어준다는 차이점이 있습니다. 리액트에서 상태를 업데이트할때는 기존 상태는 그대로 두면서 새로운 값의 상태로 설정해야합니다. 이를 불변성 유지라고합니다. 불변성 유지를 해야 리액트 컴포넌트의 성능을 최적화가 가능합니다.

 

 

3.  데이터 제거 기능 구현하기

import {useState} from 'react'

const Iteration = () => {
	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)
    
    const onChange = e => setInputText(e.target.value)
    const onClick = () => {
    	const nextNames = names.concat({
        	id : nextId,
            text : inputText
        })
        setNextId(nextId + 1)
        setNames(nextNames)
        setInputText('')
    }
    
    const onRemove = id => {
    	const nextNames = names.filter(name => name.id !== id)
        setNames(nextNames)
    }
    
    const nameList = nams.map(name => <li key={name.id} 
    onDoubleClick={() => onRemove(name.id)}>{name.text}</li>)
    return 
    <>
    <input value = {inputText} onChange = {onChange}/>
    <button>추가</button>
    <ul>{nameList}</ul>
    </>
}
export default Iteration
잠깐! 

filter 함수의 인자에 분류하고 싶은 조건을 반환하는 함수를 넣어주면 쉽게 분류가 가능합니다.
filter 함수를 응용하여 특정 배열에서 특정 원소만 제거가 가능합니다.

const number = [1, 2, 3, 4, 5, 6]
const ex = numbers.filter(number => number > 3)
// 결과는 [4, 5, 6]

만약에 특정 숫자인 3만 없애고 싶다면 다음과 같이 하면 됩니다. 

const number = [1, 2, 3, 4, 5, 6]
const ex = numbers.filter(number => number !== 3)
// 결과는 [1, 2, 4, 5, 6]

 

 

 

 

 

 

'FrontEnd > React' 카테고리의 다른 글

8장. Hooks  (0) 2023.03.19
7장. 컴포넌트의 라이프사이클 메서드  (0) 2023.03.11
5장. ref : DOM 에 이름 달기  (0) 2023.02.18
4장. 이벤트 핸들링  (0) 2023.02.11
3장. 컴포넌트  (0) 2022.12.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30