[React.js] 강좌 6-1편 컴포넌트 Iteration (반복) – Map


이 튜토리얼은 2018년에 새로운 강의로 재작성되었습니다 [새 튜토리얼 보기]

liste

이번 강좌에서는 다른 데이터를 지니고있는 같은 종류의 여러 컴포넌트를
효율적으로 렌더링 하는 방법에 대하여 알아보겠습니다.

1. JavaScript – Array.prototype.map

우선, JavaScript 의 Array 객체 내장함수인 map 함수에 대하여 알아볼까요?

정의

map() 메소드는 파라미터로 전달 된 함수를 통하여 배열 내의 각 요소를 프로세싱 하여 그 결과로 새로운 배열을 생성합니다..

문법

arr.map(callback, [thisArg])

파라미터

callback 새로운 배열의 요소를 생성하는 함수로서, 다음 세가지 인수를 가집니다.

currentValue 현재 처리되고 있는 요소

index 현재 처리되고 있는 요소의 index 값

array 메소드가 불려진 배열

thisArg (선택항목) callback 함수 내부에서 사용 할 this 값을 설정

예제

배열 [1, 2, 3, 4, 5] 의 각 요소를 제곱하여 새로운 배열을 생성하는 예제를 살펴봅시다.

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

var processed = numbers.map(function(num){
    return num*num;
});

결과: [1, 4, 9, 16, 25]

위 코드를 ES6 문법으로 작성하면 다음과 같습니다.

let numbers = [1, 2, 3, 4, 5];

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

Arrow Function?

이 코드에서 사용된 ( ) => { } 은 ES6 에 새로 도입된 arrow function 입니다.

자세한 설명은 Mozilla 참고자료를 참조하세요.

이미지 5


2. 컴포넌트 mapping

이번엔 데이터 배열을 mapping 하여 컴포넌트 배열로 변환하는 과정을 살펴보도록 하겠습니다.

React.js 작업환경이 설정되었다는 가정하에 진행하도록하겠습니다.

편의상 컴포넌트들을 App.js에 모두 작성하겠습니다.

src/components/App.js

import React from 'react';

class App extends React.Component {
    render(){

        return (
                <Contacts/>
        );
    }
}

class Contacts extends React.Component {
    render(){
        return(
            <div>
                <h1>Contacts</h1>
                <ul>
                    <li>Abet 010-0000-0001</li>
                    <li>Betty 010-0000-0002</li>
                    <li>Chalie 010-0000-0003</li>
                    <li>David 010-0000-0003</li>
                </ul>
            </div>
        );
    }
}

export default App;

txsGw

(위 버튼을 누르면 작업환경을 설정하지 않고 코드 수정 및 실행이 가능합니다)

전화번호부 기능을 하는 예제 컴포넌트 입니다.

19-22번줄, 비슷한 코드가 반복되죠? 지금 당장은 큰 문제가 없지만, 저기에 나올 데이터가 유동적이라면? 그때그때 하드코딩 하는건 좀.. 그렇겠죠? 이 문제점을 React 스럽게 해결해보도록 합시다.


2.2 ContactInfo 컴포넌트 만들기

ContactInfo 클래스 생성 (Contacts 클래스 하단)

class ContactInfo extends React.Component {
    render() {
        return(
            <li>{this.props.name} {this.props.phone}</li>
        );
    }
}

이름과 전화번호가 나타날 부분에 props 를 사용하였습니다.

Contacts 컴포넌트 렌더링 부분 수정

    render(){
        return(
            <div>
                <h1>Contacts</h1>
                <ul>
                    <ContactInfo name="Abet" phone="010-0000-0001"/>
                    <ContactInfo name="Betty" phone="010-0000-0002"/>
                    <ContactInfo name="Charlie" phone="010-0000-0003"/>
                    <ContactInfo name="David" phone="010-0000-0004"/>
                </ul>
            </div>
        );
    }

html 코드를 저희가 만든 컴포넌트 형태로 변환하여 작성하였습니다.

아직 크게 달라진건 없습니다. 같은 코드를 반복해서 사용하는건 마찬가지입니다.

txsGw


2.3 mapping

데이터를 매핑해봅시다.

기본 state 추가 (Contacts 클래스 내부)

    constructor(props) {
        super(props);
        this.state = {
            contactData: [
                {name: "Abet", phone: "010-0000-0001"},
                {name: "Betty", phone: "010-0000-0002"},
                {name: "Charlie", phone: "010-0000-0003"},
                {name: "David", phone: "010-0000-0004"}
            ]
        };
    }

state 는 컴포넌트에서 유동적인 데이터를 다룰 때 사용됩니다. 이에 대한 지식이 부족하다면 [React.JS] 강좌 5편 를 참조하세요.

렌더링 부분 배열 mapping 으로 교체

    render(){
        return(
            <div>
                <h1>Contacts</h1>
                <ul>
                    {this.state.contactData.map((contact, i) => {
                        return (<ContactInfo name={contact.name}
                                            phone={contact.phone}
                                              key={i} 
                                 />);
                    })}
                </ul>
            </div>
        );
    }

9번 줄에서 key 가 사용되었는데요, 이는 child 컴포넌트에 identity (독자성) 을 부여해줍니다.

txsGw


최종 코드

import React from 'react';

class App extends React.Component {
    render(){

        return (
                <Contacts/>
        );
    }
}

class Contacts extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            contactData: [
                {name: "Abet", phone: "010-0000-0001"},
                {name: "Betty", phone: "010-0000-0002"},
                {name: "Charlie", phone: "010-0000-0003"},
                {name: "David", phone: "010-0000-0004"}
            ]
        };
    }
    render(){
        return(
            <div>
                <h1>Contacts</h1>
                <ul>
                    {this.state.contactData.map((contact, i) => {
                        return (<ContactInfo name={contact.name}
                                            phone={contact.phone}
                                              key={i}/>);
                    })}
                </ul>
            </div>
        );
    }
}

class ContactInfo extends React.Component {
    render() {
        return(
            <li>{this.props.name} {this.props.phone}</li>
            );
    }
}

export default App;

출력물

이미지 8


마치면서..

다음 강좌에서는 이 프로젝트를 계속 사용하여 위 Contacts 컴포넌트에 ContactInfo를 추가, 제거 및 수정을 해보겠습니다.

liste

  • Changhoon Lee

    좋은 강좌 정말 감사합니다!
    2.2 첫번째 코드 첫번째 줄 Component에 오타가 있네요!

    • 어쩌다가 저런 오타가생겼징 ㅋㅋㅋ
      지적 감사합니다 😀

  • Sungtak Ryoo

    최근 React에 관심이 생겨서 공부하기 시작했는데 정말 좋은 강좌 감사드립니다.
    2.3 렌더링 부분 배열 mapping 으로 교체하는 부분의 코드에서
    에서 /> 부분을 빼먹으신것 같아요!

    • 감사합니다 : ) 수정되었어요.

  • Seongkuk Park

    react 공부중인 사람입니다. 강좌 감사합니다.!.

    마지막 최종코드 exports -> export 로 바꾸어 주셔야 할거 같아요~

  • daye Jeong

    강좌 잘보고있습니다:-)
    2.1 코드에도 exports를 export로 바꿔야할듯합니다~

  • Dongjin Han

    덕분에 잘 공부하고 있습니다 ㅎ

  • Kyungbae Ro

    감사합니다. 정주행중입니다.

  • biggerbig

    역시 벨로퍼트님 짱짱맨! api로 20개 받아서 5개만 뿌리고 싶으면 어떻게 해야 할까요?