본문 바로가기

Client/React.js

<리액트 기초> map과 props

 

1. map

 * 1차원 배열

 - map은 리액트에서 반복문을 쓸 때 아주 좋은 방법이다.

 

 - 사용법은 배열을 미리 만들고 map메서드를 불러오면 된다.

 

<ul>
    {['가','나','다','라','마'].map( () => {
        return (
            <li>hi</li>
        );
    })}
</ul>

 

 - map은 배열안의 원소들을 하나하나 돌아가면서 return결과로 바꾸는 방식이다. 여기서는 문자를 jsx태그로 바꾸고 있는 것이다. 입력과 출력의 갯수가 같음에 유의하자. 결과는 아래와 같을 것이다.

 

<ul>
    <li>hi</li>
    <li>hi</li>
    <li>hi</li>
    <li>hi</li>
    <li>hi</li>
</ul>

 -  map 안에서 첫 번째 인자를 이용하면 배열안의 원소들을 받아오는 반복문이 가능하다.

 

<ul>
    {['가','나','다','라','마'].map( (v) => {
        return (
            <li>{v}</li>
        );
    })}
</ul>

 

 - map안에 첫 번째 인자 v를 넣어주었고, 이를 리스트에 넣어주었다. 이렇게하면 다음과 같이 출력될 것이다.

 

<ul>
    <li>가</li>
    <li>나</li>
    <li>다</li>
    <li>라</li>
    <li>마</li>
</ul>

 

* 2차원 배열

 - 바뀌는 쌍을 2개로 했을 때, 2차원 배열로 만드는 방법과 객체로 만드는 방법이 있다.

 

 - 먼저 2차원 배열로 만들어보자. 배열이 복잡해지므로 따로 빼서 만들었다.

 

fruits = [
    ['사과', '빨강'],
    ['귤', '주황'],
    ['수박', '초록'],
    ['메론', '연두'],
    ['포도', '보라'],
];

render() {
    return (
        <>
            <ul>
                {this.fruits.map( (v) => {
                    return (
                        <li>{ v[0] }의 색은 { v[1] }</li>
                    )
                })}
            </ul>
        </>
    );
}

 

 - 위와 같이 따로 배열을 선언하면 this를 이용해서 불러올 수 있다. 그리고 v가 배열의 원소를 하나씩 가져오는데 여기서는 원소하나가 또 배열이므로 인덱스를 이용해서 꺼내 주었다.

 

<ul>
    <li>사과의 색은 빨강</li>
    <li>귤의 색은 주황</li>
    <li>수박의 색은 초록</li>
    <li>메론의 색은 연두</li>
    <li>포도의 색은 보라</li>
</ul>

 

 - 이번에는 객체로 만들어보자.

 

 fruits = [
        { fruit: '사과', color: '빨강'},
        { fruit: '귤', color: '주황'},
        { fruit: '수박', color: '초록'},
        { fruit: '메론', color: '연두'},
        { fruit: '포도', color: '보라'}
    ];


render() {
    return (
        <>
            <ul>
                {this.fruits.map( (v) => {
                    return (
                        <li>{ v.fruit }의 색은 { v.color }</li>
                    )
                })}
            </ul>
        </>
    );
}

 

 - 결과는 당연히 위에서 했던 것과 같다.

 

 - 참고로 map에서 두 번째 인자로 인덱스 값을 가져오는 것도 가능하다. 이 때는 map( (v, i) => {}) 와 같이 사용해서 i를 이용하면 된다.

 

 - 위의 코드들에는 한 가지 문제가 있다. 바로 key이다. 반복을 돌 때 고유한 키값을 추가해야한다. 예를 들면 위드 li태그를 다음과 같이 수정해야한다.

 

<li key={v.fruit + v.color}>
    { v.fruit }의 색은 { v.color }
</li>

 

 - key는 반드시 고유한 값이어야 하므로 최대한 중복이 나지 않는 값을 받도록 하였다.

 

 - 또 다른 문제가 있는데, 이는 반환하는 코드블럭이 너무 길어질 수 있다는 것이다. 이럴 때에는 또 다른 컴포넌트 파일로 만드는 것이 낫다. 이는 따로 아래 props에서 살펴보자.

 

* reduce 사용하기

 - 반복문과 비슷한 기능을 활용하기 위해서 reduce를 배열에 활용하는 것도 좋다. reduce는 배열을 순회하며 단 하나의 결과값을 얻어내고 싶을 때 사용하자.

 

 - 배열.reduce ( (a, c) => a + c) 와 같이 사용한다. a와 c는 임의의 변수인데, a는 누적값을, c는 현재값을 나타낸다. 두 개의 함수 인자를 이용해서 함수를 만들면 된다. 

 

 - 배열의 평균을 jsx태그안에서 구현해보자.

 

<!-- 
const { result } = this.state 
...
-->
<div>
    평균 : {result.reduce( (a, c) => a + c ) / result.length}
</div>

 - result라는 배열을 순회하면서 합을 누적시켜서 총합을 구해내고, 그것을 배열의 길이로 나누어서 평균을 구했다.

 

 - 참고로 세 번째 인자로 인덱스 값을 받을 수 있다.

2. props

 - 앞서 작성했던 태그를 별도의 compo.jsx파일에 컴포넌트로 만들어주었다.

 

import React, { Component } from 'react';

class Compo extends Component {
    render() {
        const { valInfo } = this.props;
        return (
            <li>
                { valInfo.fruit }의 색은 { valInfo.color }
                <div>내용내용</div>
            </li>
        )
    }
}

export default Compo;

 

 - 외부로 내보내기 위해서 export 를 해줬음을 알 수 있다.

 

 - 여기서 props가 등장하는데 구조분해 문법으로 this.props를 생략해주었지만 어쨋든 태그 안에서 내용들이 앞에서 봤던 v.fruit가 아니라는 것은 알 수 있다. 앞서 봤던대로 v를 바로 쓰면 v를 인식하지 못한다. 따라서 기존의 파일에서 넘겨준 값을 받도록 this.props를 이용한다. 기존의 파일은 다음과 같이 작성되어 있다.

 

render() {
    return (
        <>
            <ul>
                {this.fruits.map( (v) => {
                    return (
                        <Compo key={v.fruit + v.color} valInfo={v}/>
                    )
                })}
            </ul>
        </>
    );
}

 - import는 따로 적어두진 않았지만 반드시 해야한다.

 

 - map에서 return으로 <Compo /> 를 하고 있음을 알 수 있다. 여기서 key는 아까와 같이 유일한 값을 갖게 하였고, valInfo라는 임의의 props (html에서는 attribute의 역할) 을 정해서 상속 시켜주었다.

 

 - hook에서 props를 쓰려면 다음과 같이 작성하면 된다.

 

import React from 'react';

const Compo = ({valInfo}) => {
    return (
        <li>
            <div>{ valInfo.fruit }의 색은 { valInfo.color }</div>
        </li>
    )
}

export default Compo;

 

 - 화살표 함수의 인자로 props.valInfo가 기본적이지만 props. 을 반복 작성해야함을 피하기위해서 구조분해 문법을 사용하였다.

 

 - 부모로 받은 props를 직접적으로 값을 바꾸면 안된다. props는 반드시 부모가 바꿔야하는데, 만약 바꿔야하는 상황이라면 state를 만들고 거기에 넣어서 사용해야한다. 이렇게 하면 부모에는 영향이 가지 않는다.

 

 - 위의 코드에서 props를 변경하려면 아래와 같이 작성하면 된다.

 

import React, { useState } from 'react';

const Compo = ({valInfo}) => {
    const  [color, setColor] = useState(valInfo.color);
    
    const onClick = () {
    	setColor('몰라');
    };
    return (
        <li>
            <div>{ valInfo.fruit }의 색은 { valInfo.color }</div>
            <div onClick={onClick}>{color}</div>
        </li>
    )
}

export default Compo;

 

 - 컴포넌트 내부에서 state를 별도로 다시 선언하였고, useState로 값을 불러왔다. 

 

 - 클래스 컴포넌트도 마찬가지로 state = { } 로 state를 선언하고 필요한 부분들을 다시 선언하고 변화시켜야한다.

 


 

 

참고

 

 

이 글은 ZeroCho 님의 리액트 무료 강좌를 수강하며 개인적으로 정리하며 쓰는 글입니다.

 

 

 

 

인프런

 

웹 게임을 만들며 배우는 React - 인프런

웹게임을 통해 리액트를 배워봅니다. Class, Hooks를 모두 익히며, Context API와 React Router, 웹팩, 바벨까지 추가로 배웁니다. 초급 웹 개발 프레임워크 및 라이브러리 React 웹 개발 게임개발 온라인 강

www.inflearn.com

 

유튜브

 

리액트 무료 강좌(웹게임)

 

www.youtube.com