React) 컴포넌트 반복

iamokian·2022년 3월 22일
0

React

목록 보기
6/10

6. 컴포넌트 반복

웹 애플리케이션을 만들다 보면 반복되는 코드를 작성할 때가 있다. (ul태그안의 li같은 것들) 하지만 코드가 좀 더 복잡하다면 어떨까? 코드의 양도 늘어나고, 파일의 용량도 증가할 것이다. 이는 낭비이다. 또한 보여주어야 할 데이터가 유동적이라면 이런 코드는 관리하지 못한다. 그럴때 효율적으로 보여주고 관리하는 방법을 알아보자.


6-1. 자바스크립트 배열의 map()함수

JS배열 객체의 내장 함수인 map함수를 사용해 반복되는 컴포넌트를 렌더링할 수 있다. map 함수는 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 그 결과로 새로운 배열을 생성한다.

👀map 문법?

arr.map(callback, [thisArg])

*callback : map함수의 파라미터는 세 가지 이다.
	- currentValue : 현재 처리하고 있는 요소
    - index : 현재 처리하고 있는 요소의 index 값
    - arry : 현재 처리하고 있는 원본 배열
*thisArg(선택 항목) : callback함수 내부에서 사용할 this 레퍼런스

6-2. 데이터 배열에서 컴포넌트 배열로

위 map문법을 활용해 컴포넌트 반복 샘플코드를 짜보자.


const InterationSample = () => {
	const names = ['눈사람', '얼음', '눈', '바람'];
  	const nameList = names.map(name => <li>{name}</li>);
    return <ul>{nameList}</ul>;
}

export default InterationSample;

문자열로 구성된 배열을 선언 후 그 배열값을 사용해 JSX코드로 된 배열을 새로 생성한 후 namsList에 담는다. map함수에서 JSX를 작성할 때는 DOM요소를 작성해도 되고, 컴포넌트를 사용해도 된다.
하지만 위와같이 컴포넌트를 만들고 App컴포넌트에서 해당 컴포넌트를 렌더링하면 콘솔창에 경고메세지가 뜰것이다

Warning: Each child in a list should have a unique "key" prop.

해당 메세지는 "key" prop 가 없다는 경고메세지이다.


6-3. key

리액트에서 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내려고 사용한다. key값을 사용하여 어떤 변화가 일어났는지 더욱 빠르게 알아낼 수 있다.

예제를 변경해보자


const InterationSample = () => {
	const names = ['눈사람', '얼음', '눈', '바람'];
  	const nameList = names.map((name, index) => <li key={index}>{name}</li>);
    return <ul>{nameList}</ul>;
}

export default InterationSample;

이제 개발자 도구에서 더이상 경고 메시지를 표시하지 않는다. 고유한 값이 없을 때만 index값을 key로 사용해야 한다. index로 key로 사용하면 배열이 변경될 때 효율적으로 리렌더링 하지 못한다.


6-4. 응용해보기

고정된 배열을 렌더링하는 것이 아닌, 동적인 배열을 렌더링하는 것을 구현해보자. 그리고 index값을 key로 사용하면 리렌더링이 비효율적이라고 하였다. 그렇다면 어떻게 고윳값을 만드는지도 알아보자.

1-1. 초기 상태 설정하기

useState를 사용하여 상태를 설정해 보자. 상태는 데이터 배열, 텍스트를 입력할 수 있는 input 상태, 데이터 배열에서 새로운 항목을 추가할 때 사용할 고유 id를 위한 상태. 이렇게 총 3가지를 설정할 것이다.


import React, { useState } from 'react';

const InterationSample = () => {
  	const [names, setNames] = useState([
      { id: 1, text: '눈사람'},
      { id: 2, text: '얼음'},
      { id: 3, text: '눈'},
      { id: 4, text: '바람'}
    ]);
	const [inputText, setInputText] = useState('');
  	//새로운 항목을 추가할 때 사용할 id
  	const [nextId, setNextId] = useState(5);
  
  	const nameList = names.map(name => <li key={name.id}>{name.text}</li>);
    return <ul>{nameList}</ul>;
}

export default InterationSample;

key값에 index대신 name.id 값을 지정해주었다.

1-2. 데이터 추가/제거 기능 구현하기

만들어둔 input과 button을 새로 만들어 새로운 이름을 등록하고 데이터를 제거하는 기능을 만들어 보자.


import React, { useState } from 'react';

const InterationSample = () => {
  	const [names, setNames] = useState([
      { id: 1, text: '눈사람'},
      { id: 2, text: '얼음'},
      { id: 3, text: '눈'},
      { id: 4, text: '바람'}
    ]);
	const [inputText, setInputText] = useState('');
  	//새로운 항목을 추가할 때 사용할 id
  	const [nextId, setNextId] = useState(5);
  	
  	const onChange = e => setInputText(e.target.value);
  	const onClick = () => {
      	const nextNames = names.concat({
        	id: nextId,
          	text: inputText
        });
      	//nextID 값에 1을 더해준다
      	setNextId(nextId + 1);
     	// names 값을 업데이트 한다
      	setNames(nextNames);
      	//inputText값을 비운다.
      	setInputText('');
    };
  	const onRemove = id => {
    	const nextNames = names.filter(name => name.id !== id);
      	setNames(nextNames);
    };
  
  	const nameList = 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 InterationSample;

컴포넌트 배열을 렌더링할 때는 key 값 설정에 항상 주의해야 한다. 또 key 값은 언제나 유일해야 한다. key 값이 중복된다면 렌더링 과정에서 오류가 발생한다. 그리고 상태 안에서 배열을 변형할 때는 배열에 직접 접근하여 수정하는 것이 아니라 concat, filter 등의 배열 내장 함수를 사용하여 새로운 배열을 만든 후 이것을 새로운 상태로 설정해주여야 한다.


리액트를 다루는 기술을 읽고 요약한 글 입니다😊

profile
필기하고 기록하고

0개의 댓글