[React] React Basic - (5) 배열 다루기 1

React Basic - (5) 배열 다루기 1

React 배열의 속성

  • 리액트에서는 state 내부의 값을 직접적으로 수정하면 절대로 안됨!! => 불변성 유지
  • push, splice, unshift, pop 같은 내장함수는 배열 자체를 직접 수정하게 되므로 적합하지 않음
  • 기존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, map, filter 같은 함수를 사용해야 함.

⇒ 불변성을 유지해야, 리액트에서 모든것들이 필요한 상황에 리렌더링 되도록 설계할 수 있고, 성능도 최적화할 수 있다.

Map 함수

const a = [1,2,3,4,5];
const b = a.map(number => number * 2);

컴포넌트 만들기

PhoneInfo : 각 전화번호의 정보를 보여주는 컴포넌트

PhoneInfoList : 여러 개의 PhoneInfo 컴포넌트를 보여줌

배열에 추가되는 과정

  1. App에서 PhoneForm의 onCreate 파라미터에 handleCreate() 할당
  2. PhoneForm에서 submit을 클릭해 handleSubmit()이 호출되면, 부모 컴포넌트 (App)의 onCreate에 현재 상태(name, phone)인 this.state가 할당됨
  3. App의 handleCreate()가 호출되면, 받아온 data를 바탕으로 information 정보가 추가됨 (id는 하나씩 증가)
  4. PhoneInfoList에는 현재 information정보가 파라미터로 할당되므로, information 배열이 추가될 때마다 받아온 data를 map을 통해 변환한 list가 리렌더링됨.

전체 Code

App.js

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

class App extends Component {
  id = 2
  state = {
    // state에는 렌더링되는 값만 넣어줌
    information : [
      {
        id : 0,
        name : 'paige',
        phone : '010-0000-0000'
      },
      {
        id : 1,
        name : 'tiger',
        phone : '010-1111-1111'
      }
    ]
  }
  handleCreate = (data) => {
    const {information} = this.state;
    this.setState({
      information : information.concat({
        id:this.id++, ...data
      })
    })
    console.log(data);
  }
  render() {
    const {information} = this.state;
    return (
      // <Counter/>
      <div>
        {/* PhoneForm : input 관리 */}
        <PhoneForm
          onCreate={this.handleCreate}/>
        <PhoneInfoList
          // data에 현재 information 배열을 할당함
          data={this.state.information}/>
      </div>
    );
  }
}

export default App;

PhoneForm.js

import React, {Component} from 'react';

class PhoneForm extends Component {
    state = {
        name : '',
        phone : ''
    }
    // input의 onChange가 발생하면 호출되는 함수
    handleChange = (e) => {
        this.setState({
            // [e.target.name] : 이벤트가 발생한 input의 name
            [e.target.name] : e.target.value
        });
        // => 현재 input 상태를 이벤트 객체의 텍스트 값으로 변경
    }
    handleSubmit = (e) => {
        // 페이지 리로딩 방지
        e.preventDefault();
        // 상태값을 onCreate를 통하여 부모에게 전달
        this.props.onCreate(this.state);
        // 상태 초기화
        this.setState({
            name:'',
            phone:''
        });
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input 
                    placeholder="이름"
                    // submit을 클릭하면 초기화되도록 하기 위해 {this.state.name}객체 할당
                    value={this.state.name}
                    onChange={this.handleChange}
                    // input의 name으로 각 input을 구분함
                    name="name"
                />
                <input
                    placeholder="전화번호"
                    value={this.state.phone}
                    onChange={this.handleChange}
                    name="phone"
                />
                <button type="submit">등록</button>
            </form>
        );
    }
}
export default PhoneForm;

PhoneInfo.js

import React, {Component} from 'react';

class PhoneInfo extends Component {
    // defaultProps을 통하여 info의 기본값 설정 => 컴포넌트가 undefined 되는 것 방지
    static defaultProps = {
        info: {
            name: '이름',
            phone: '010-0000-0000',
            id: 0
        }
    }
    render() {
        const style = {
            border: '1px solid black',
            padding: '8px',
            margin: '8px'
        };
        const {name, phone, id} = this.props.info;
        return (
            <div style={style}>
                <div>
                    <b>{name}</b>
                    <b>{phone}</b>
                </div>
            </div>
        );
    }
}
export default PhoneInfo;

PhoneInfoList.js

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

class PhoneInfoList extends Component {
    static defaultProps = {
        data : []
    }
    render() {
        // 부모 컴포넌트 (PhoneInfo)에서 data를 받아옴
        const {data} = this.props;
        // 받아온 data를 map을 통하여 컴포넌트로 반환해 list에 저장
        const list = data.map(
            info => (
            <PhoneInfo key={info.id} info={info}/>)
        );
        return (
            <div>
                {list}
            </div>
        );
    }
}
export default PhoneInfoList;