이미지09
Coding Story/REACT

[ React ] 리액트 Map 과 데이터 랜더링

반응형

 

 

 

이번 게시글에선 Map 을 사용해 데이터를 직접 랜더링해보는 과정을 볼 것이다.

이전 게시글의 소스를 기반으로 수정하여 사용했음을 참고.

이번엔 직원이름, 연차를 입력받아 등록하는 화면을 만들고자 한다.

사용하게 될 js 파일을 먼저 요약정리부터 해본다면 아래와 같다.

App.js - 메인컴포넌트. UserInput.js ( 입력폼 ) 과 UserProfileList.js ( UserProfile Data List ) 를 호출.
UserInput.js - 신규 유저를 등록하는 입력폼 컴포넌트.
UserProfileList.js - 유저의 정보 ( JSX ) 를 가지고 있는 List 컴포넌트.
UserProfile.js - 각각 개별의 유저 정보 컴포넌트.

먼저 메인 컴포넌트인 App.js 부터 살펴보자

 

 

 

App.js

import { render } from '@testing-library/react';
import React, { Component } from 'react';
import './App.css';
import UserInput from './UserInput';
import UserProfileList from './UserProfileList';

class App extends Component {
  //Map 에서 사용 될 고유성을 가리기 위한 key
  id = 0;

  state = {
    userInfo: []
  }
  
  loginUserHistory = (data) => {
    const {userInfo} = this.state;
    //userInfo 배열에 UserInput 컴포넌트, UserProfileList 컴포넌트에서 return 받은 data 와 id 를 넣는다
    this.setState({
      userInfo: userInfo.concat({
        id: this.id++, ...data
      })
    })
  }

  render() {
    return (
       <div>
          {/* UserInput 컴포넌트 호출, return 받은 후 loginUserHistory 함수 호출 */}
          <UserInput onCreate={this.loginUserHistory} />
          {/* UserProfileList 컴포넌트 호출 */}
          <UserProfileList data={this.state.userInfo} />
        </div>
    );
  }
}

export default App;

 

간단하게 사이클만 설명하자면 render 함수에서 UserInput.js 컴포넌트를 호출했다.

그렇다는건 UserInput 에서 return 해주는 데이터가 현 컴포넌트 ( App.js ) 로 올테고,

이 데이터를 loginUserHistory 함수에서 userInfo 배열안에 집어넣어준다.

그 후 render 함수에서 UserProfileList 를 호출하는데 이 때 parameter 로 현 state 에 있는 userInfo 를 보낸다.

밑에서 나오겠지만 먼저 앞서 말하자면 userInfo 배열 안의 data 는 Map 이 들어가있다.

컴포넌트를 하나하나 살펴보자.

render 함수에서 호출한 UserInput.js 컴포넌트는 다음과 같다.

 

 

 

UserInput.js

import React, {Component} from 'react';

class UserInput extends Component {
    
    //state 에 userName, year 초기화
    state = {
        userName: '',
        year: ''
    }

    inputChange = (e) => {
        this.setState({
            //key : value
            [e.target.name]: e.target.value
        })
    }

    loginUser = (e) => {
        //submit 후 reload 방지
        e.preventDefault();

        //부모에서 넘어온 onCreate 호출해 state 전달
        this.props.onCreate(this.state);

        //state 초기화
        this.setState({
            userName: '',
            year: ''
          })
    }

    render() {
        return (
            <form onSubmit={this.loginUser}> 
                <input type='text' name='userName' placeholder='이름을 입력하세요' onChange={this.inputChange} value={this.state.userName}/>
                <input type='text' name='year' placeholder='연차를 입력하세요' onChange={this.inputChange} value={this.state.year}/>

                <button type='submit'>등록</button>
            </form>
        )
    }
}
export default UserInput;

 

UserInput.js 컴포넌트는 이전 게시글의 User.js 컴포넌트와 별 다를게 없다. 파일명만 바뀌었을 뿐이다.

 

 

 

 

UserProfileList.js

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

class UserProfileList extends Component {
  static defaultProps = {
    data: []
  }

  render() {
    //App.js 컴포넌트에서 호출할 때 넘겨준 data 들어감.
    const { data } = this.props;

    //data 배열을 map 으로 변환해준다. 이 때 UserProfile.js 컴포넌트를 호출.
    const userInfoMap = data.map(
        info => (<UserProfile key={info.id} info={info}/>)
    );

    return (
      <div>
        {/* 위에 변환된 userInfoMap 을 return 해준다 */}
        {userInfoMap}    
      </div>
    );
  }
}

export default UserProfileList;

 

주석으로 이미 설명했지만 다시 한번 더 풀어 보자면,

this.props 는 App.js 에서 현 컴포넌트를 호출하며 넘겨준 배열이다.

이 배열을 map 으로 변환하는 과정인데

const userInfoMap = data.map(
    info => (<UserProfile key={info.id} info={info}/>)
);

 

UserProfile.js 컴포넌트를 호출하는데 이 때 parameter 로 key : info.id 와 info : info 를 보낸다.

그럼 호출되어지는 UserProfile.js 컴포넌트 입장에서는 info.id 와 info 를 사용하게 될 것이다.

UserProfile.js 컴포넌트에서 이런 저런 일을 한 후 현 컴포넌트 ( UserProfileList.js ) 로 값을 return 해주고,

이 값은 map 으로 변환되어 userInfoMap 에 넣어진 뒤 자신을 호출한 App.js 컴포넌트로 return 해주는 로직이다.

그럼 다음은 배열을 맵으로 변환하는 과정에서 호출한 UserProfile.js 컴포넌트를 살펴보자.

 

 

 

 

UserProfile.js

import React, { Component } from 'react';

class UserProfile extends Component {
  //신규 유저를 등록하기 전 최초 화면이 로딩될 때도 호출이 되는데 이 때는 data 가 존재하지 않음. default 초기화 선언.
  static defaultProps = {
  info: {
      userName: '이름',
      year: 0,
      id: 0
    }
  }
  
  //연차에 따라 직급을 return 해주는 함수 ( 연차 기준은 임의로 정한 조건임 )
  checkYear = (year) => {
    if(year == 0) {
        return '신입';
    }
    if(year == 1) {
        return '사원';
    }
    if(year == 2) {
        return '대리';
    }
    if(year >= 3 && year <= 4) {
        return '과장';
    }
    if(year >= 5 && year <= 6) {
        return '차장';
    }
    if(year >= 7 && year <= 10) {
        return '부장';
    }
    if(year > 10) {
        return '사장';
    }
  }

  render() {
    //https://velopert.com/3636 블로그를 참고해 공부하는 중인데 만들어놓으신 style 적용했음
    const style = {
      border: '1px solid black',
      padding: '8px',
      margin: '8px'
    };

    //userName, year, id 각자 UserProfileList.js 컴포넌트에서 넘어온 데이터 할당
    const { userName, year, id } = this.props.info;
    
    return (
      <div style={style}>
        <div><b>이름 : {userName}</b></div>
        <div>연차 : {year}년</div>
        <div>직급 : {this.checkYear(year)}</div>
      </div>
    );
  }
}

export default UserProfile;

 

이 컴포넌트는 블록별로 상세하게 살펴보도록 하자.

위에서 언급했 듯 UserProfileList.js 컴포넌트에서 key : info.id 와 info : info 를 보내주었다.

UserProfile.js 컴포넌트가 위 쪽에 아래와 같이 defaultProps 로 info 를 선언해 놓았기에,

static defaultProps = {
  info: {
      userName: '이름',
      year: 0,
      id: 0
  }
}

 

this.props.info 만 해도 현 컴포넌트에서 선언한 info 의 userName, year, id 는

 

parameter 로 넘어온 userName, year, id 와 일치하니

바인드되어 userName, year, id 에 값이 들어가게 되는 것이다.

const { userName, year, id } = this.props.info;

 

그 후 return 하고자 하는 JSX 문법 내에서 this.checkYear 함수를 호출했고,

year 의 값에 따라 직위를 return 해 완성된 JSX 문법으로 return 해주게 되는 것이다.

checkYear = (year) => {
    if(year == 0) {
        return '신입';
    }
    if(year == 1) {
        return '사원';
    }
    if(year == 2) {
        return '대리';
    }
    if(year >= 3 && year <= 4) {
        return '과장';
    }
    if(year >= 5 && year <= 6) {
        return '차장';
    }
    if(year >= 7 && year <= 10) {
        return '부장';
    }
    if(year > 10) {
        return '사장';
    }
  }

.
.
.

...
return (
   <div style={style}>
      <div><b>이름 : {userName}</b></div>
      <div>연차 : {year}년</div>
      <div>직급 : {this.checkYear(year)}</div>
   </div>
);

 

 

 

 

실행화면

 

포스팅 이미지 01

 

이름과 연차를 입력 후 버튼을 클릭하면 아래에 새로운 data 가 생길 것이다.

 

 

 

반응형