React/velopert_react

배열 렌더링하기

느리지만 꾸준하게 2021. 8. 20. 17:56

이번에는 JavaScript 배열 내장함수 map에 대해서 알아보자. map이라는 내장함수의 용도는 배열을 특정함수를 사용하여 전체적으로 변환해주고 싶을 때 사용하는 함수이다.

 

리액트 프로젝트에서 사용하기 전에 Chrome console에서 사용해보도록 하자.

 

숫자로 이루어진 배열 하나를 만들자. numbers배열을 가지고 안에 값들을 전부 제곱하는 것을 작성해본다. 

원래는 for문을 이용해서 제곱시키는 코드를 작성할 수도 있지만 map을 이용하면 numbers.map해서 함수를 작성해주는 것이다. 함수는 내부에 있는 n값들을 n * n으로 만들어라이다.

st numbers = [1,2,3,4,5];
undefined

const squared = numbers.map(n => n * n);
undefined

squared
(5) [1, 4, 9, 16, 25]

컴포넌트 두개를 먼저 만들어주자.(PhoneInfo.js , PhoneInfoList.js)

PhoneInfo에서 rcc를 누르고 작성한다.  

import React, { Component } from 'react';

class PhoneInfo extends Component {
    render() {
        return (
            <div>
                
            </div>
        );
    }
}

export default PhoneInfo;

props를 받아올 건데 props를 비구조할당을 통해서 name값이랑 phone값이랑 id값을 받아온다. info라는 값을 전달받을 꺼고 그 안에서 name phone id 값을 각각 추출해준다. 그리고 div 사이에 이름과 폰이 나타나게 한다.

 

스타일도 간단히 자바스크립트로 작성한다. 그리고 PhoneInfoList.js 파일을 컴포넌트폴더안에 하나 또 만든다.

import React, { Component } from 'react';

class PhoneInfo extends Component {
    render() {
        const { name, phone, id } = this.props.info;

        const style = {
            border: '1px solid black',
            padding: '8px',
            margin: '8px',
        };
        return (
            <div style={stylr}>
                <div><b>{name}</b></div>
                <div>{phone}</div>
            </div >
        );
    }
}

export default PhoneInfo;

PhoneInfoList.js파일안에 rcc를 해주고 PhoneInfo를 import해준다.

그리고 data값을 props로 받아와 주는데 list라는 값을 만들건데 map을 이용해서 data안에 있는 info라는 것을 PhoneInfo 컴포넌트한테 전달을 해줄건데, info={info}로 넣어준다.

 

key 값도 필요한데 컴포넌트를 여러개 rendering할 때 고유값을 정해줌으로써 나중에 업데이트 성능을 최적화 해주는 것이다. 즉 key에다가 info.id값을 넣어준다. {list}를 넣어주어서 렌더링도 해준다.

import React, { Component } from 'react';
import PhoneInfo from './PhoneInfo';


class PhoneInfoList extends Component {
    render() {
        const { data } = this.props;
        const list = data.map(
            info => (<PhoneInfo info={info} key={info.id} />)
        )
        return (
            <div>
                {list}
            </div>
        );
    }
}

export default PhoneInfoList;

 위에서 숫자로 이루어진 배열을 가지고 제곱을 해주었는데 이번에는 info들의 배열을 가지고 PhoneInfo 컴포넌트로 변환을 해준 것이다. 그리고 밑에 {list}로 렌더링을 해주었다.

 

만약 this.props에 데이터가 전달받지 않았더라면 data가 배열이 아니므로 랜더링 할 수 없다고 오류가 뜰 것이다. App.js에서 이 부분을 

{JSON.stringify(this.state.information)}

PhoneInfoList를 임포트 해주고 아래와 같이 렌더링 해주면 오류가 나타난다.

<PhoneInfoList />


//TypeErro: Cannot read property 'map' of undefined

에러를 해결하기 위해 PhoneInfoList에서 데이터가 없으면 null을 리턴해주면 된다.

class PhoneInfoList extends Component {
    render() {
        const { data } = this.props;


// 달라진 부분
        if (!data) return null;
        const list = data.map(
            info => (<PhoneInfo info={info} key={info.id} />)
        )
        return (
            <div>
                {list}
            </div>
        );
    }
}

// PhoneInfoList.js

 

또는 컴포넌트에 defaultProps를 정해줄 수가 있다. data값을 [] 빈배열로 하고 defaultProps를 정해줄 때는 앞에다가 static값을 넣어준다.

class PhoneInfoList extends Component {
// 달라진 부분
    static defaultProps = {
        data: []
    }


    render() {
        const { data } = this.props;

        const list = data.map(
            info => (<PhoneInfo info={info} key={info.id} />)
        )
        return (
            <div>
                {list}
            </div>
        );
    }
}

PhoneInfoList에다가 information값을 전달해주면 아래와 같이 된다.

// App.js

  render() {
    return (
      <div>
        <PhoneForm onCreate={this.handleCreate} />
        <PhoneInfoList data={this.state.information} />
      </div>
    );
  }
}

 

아까전에 PhoneInfoList에서 렌더링할 때 key값을 넣어주었는데 key는 어떠한 역할을 하는 것일까?

 

배열을 렌더링 할 때 사용하는 key가 있는데 key가 없다면 (그림 넣어주기) a b c d 라는 내용이 있는 배열이 있다고 가정하자.

배열내용을 가지고 div 엘리먼트를 만들어준다. 만약 b와 c사이에 z라는 녀석이 오면 div내용에 c가 z로 바뀌고 d가 c로 바뀌게 된다. 그리고 아래에 d가 새로 생기게 된다.

 

그리고 a가 사라지게 된다면 a가 있던 자리에 b가 들어가게 되고 b가 z로 바뀌고 z가 c로바뀌고 c가 d로 바뀌고 마지막 d가 사라지게 된다. 굉장히 비효율적이다.

만약에 key가 있다면

1이랑 2사이에 5가 있다고 가정하면 다른 것들이 가만히 있고 1과 2사이에만 id 5를 가지고 있는 z가 생기게 된다. 

만약에 id가 0인 a값이 지워졌다. 그러면 그값만 사라지게 된다.

 

key는 결국 리액트에서 내부적으로 무언가를 제거하거나 추가를 하게 될때 그러한 작업을 효율적으로 하기위해서 사용되는 값이다.

 

만약에 코드에서 key값이 없으면 어떻게 될까? 기본적으로 배열의 인덱스 0번째 1번째 즉 배열의 인덱스가 키로 사용되고 있다. 

    render() {
        const { data } = this.props;

        const list = data.map(
            info => (<PhoneInfo info={info} />)
        )
        return (
            <div>
                {list}
            </div>
        );
    }

그렇지만 지금은 id값을 추가할 때마다 값을 1씩 더하도록 설정을 하였다. 

그러나 이것이 인덱스랑 완전히 다른점은 나중에 제거 추가할 때

제거를 하게되면 id값이 인덱스랑 다르게 작동하게 된다. 왜냐하면 위에서 1 2를 삭제한다고 해서 밑에 3 4의 id가 0이 되지는 않기 때문이다.

class App extends Component {

  id = 0;

  state = {
    information: [],
  }

  handleCreate = (data) => {
    const { information } = this.state;
    this.setState({
      information: information.concat(Object.assign({}, data, {
        id: this.id++
      }))
    });
  }

이후에 데이터를 삭제하고 수정하는 거에 대해서 알아보자

 

 

<출처 : velopert(김 민준) 누구든지 하는 리액트: 초심자를 위한 react 핵심 강좌>

https://www.inflearn.com/course/react-velopert/dashboard

 

누구든지 하는 리액트: 초심자를 위한 react 핵심 강좌 - 인프런 | 강의

리액트를 누구든지 쉽고 재밌게 시작 할 수 있도록 만들어진 강좌입니다., React 핵심 강좌 초심자를 위한 리액트(React) 핵심 강좌입니다. 만약에 여러분이 리액트를 배우고 싶은데, 아직 뭐가 뭔

www.inflearn.com