본문 바로가기
컴퓨터 사이언스/TIL 정리

[리액트를 다루는 기술] 컴포넌트 반복

by 메리뉴데이 2022. 8. 15.

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

 

const numbers = [ 1, 2, 3, 4, 5];
const result = numbers.map(num => num * num);

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

 

import React from 'react';

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

export default IterationSample;

map으로 생성된 배열 값을 사용하여 JSX 코드로 된 배열을 새로 생성한 뒤 nameLIst에 담았다.

 

 

리액트에서 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내기 위해 key를 사용하고, key 값(언제나 유일한 고유값이어야 함)을 설정할 때는 map 함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 된다. 이 때 map 함수에 전달되는 콜백 함수의 인수인 index 값을 사용하면 된다.

하지만, index를 key로 사용하면 배열이 변경될 때 효율적으로 리렌더링하지 못한다 !

 

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

export default IterationSample;

 

 

유동적인 데이터 렌더링

 

초기 상태 설정하기 → 데이터 추가 기능 구현하기 → 데이터 제거 기능 구현하기

 

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 nameList = names.map( name => <li key={name.id}>{name.text}</li>);
    return <ul>{namesList}</ul>;
};

export default IterationSample;    

위에서는 map 함수를 사용할 때 key 값을 index 대신 name.id 값으로 지정해 주었다.

 

 

새로운 이름을 등록할 수 있는 기능을 구현해보면 다음과 같다.

 

const onChange = e => setInputText(e.target.value);
const onClick = ( ) => {

    const nextNames = names.concat({
        id: nextId,     // nextId 값을 id로 설정하고
        text: inputText
    });
    setNextId(nextId + 1);     // nextId 값을 id로 설정하고
    setNames(nextNames);     // names 값을 업데이트한다.
    setInputText(' ');     // 기존의 inputText를 비운다.
};
...
return (
    <>
        <input value={inputText} onChange={onChange} />
        <button onClick={onClick}>추가</button>
        <ul>{nameList}</ul>
    </>
 );

push는 기존 배열을 변경하게 되므로, concat으로 새로운 배열을 만들어 주었다. 

리액트에서는 상태를 업데이트할 때 기존 상태를 그대로 두면서 새로운 값을 상태로 설정해야 한다.((불변성 유지))

이렇게 불변성 유지를 해줘야 리액트 컴포넌트의 성능을 최적화할 수 있다.

 

 

불변성을 유지하면서 배열의 특정 항목을 지울 때는 배열의 내장 함수 filter를 사용한다.

 

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)}>     // HTML 요소를 더블클릭할 때
        {name.text}
    </li>
));

 

!! 컴포넌트 배열을 렌더링할 때는 각각 유일한 key 값 설정

!! 상태 안에서 배열을 변형할 때는 concat, filter 등의 배열 내장 함수로 새로운 배열을 만든 뒤에 새로운 상태로 설정