리액트 배열 다루기

뿌이·2022년 4월 14일
0

react 15버전

목록 보기
4/17

벨로퍼트 7편
보고 실습한 글입니다.

리액트애서는 state 내부의 값을 직접적으로 수정하면 절대로 안됩니다. 이를 불변성 유지라고 하는데요,
push, splice, unshift, pop 같은 내장함수는 배열 자체를 직접 수정하게 되므로 적합하지 않습니다. 그 대신에, 기존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, map, filter 같은 함수를 사용해야합니다.

App.js

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

class App extends Component {
  id = 2
  state = {
    information: [
      {
        id: 0,
        name: '김민준',
        phone: '010-0000-0000'
      },
      {
        id: 1,
        name: '홍길동',
        phone: '010-0000-0001'
      }
    ]
  }
  handleCreate = (data) => {
    const { information } = this.state;
    this.setState({
      information: information.concat({ id: this.id++, ...data })
    })
  }
  render() {
    return (
      <div>
        <PhoneForm
          onCreate={this.handleCreate}
        />
        <PhoneInfoList data={this.state.information}/>
      </div>
    );
  }
}

export default App;

PhoneForm.js

import React, { Component } from 'react';

class PhoneForm extends Component {
  state = {
    name: '',
    phone: '' //state에 name속성이 있어야 state.name, state.phone으로 불러올 수 있음.
  }
  handleChange = (e) => {
    this.setState({
        [e.target.name]: e.target.value //여기서 name은 name속성을 말하는 것인데, 
        //배열로 감싼 이유는 여러개 를 e.target.value로 넣어주려고 그런듯
    })
  }
  handleSubmit = (e) => {
    // 페이지 리로딩 방지 (원래 form에서 submit이 발생하면 페이지 리로딩이되는데, 
    // 그러면 우리가 지니고있는 상태값을 다 잃어버리므로 방지시킴)
    e.preventDefault(); //원래 이벤트가 해야하는 작업 방지
    
    // 상태값을 onCreate 를 통하여 부모에게 전달 (props로 애초에 부모인 App.js에서 
    // onCreate함수가 정의되어있는데, 그 함수를 그냥 쓴거다. 자식에서 그러니까
    // 사실은 여기서 부모에게 전달해준다고 이해한다기 보다는 , 부모에서 PhoneForm에다가 
    // onCreate함수를 써놨기 때문에 상태값을 전달해줄 수밖에 없는 것이다.)
    this.props.onCreate(this.state);
    // 상태 초기화
    this.setState({
      name: '',
      phone: ''
    })
  }
  render() {
    return (
        // onSubmit을 안써주면 말짱도루묵ㅋㅋ
      <form onSubmit={this.handleSubmit}>
        <input
          placeholder="이름"
          value={this.state.name}
          onChange={this.handleChange}
          name="name" //name 속성 설정 필수
        />
       <input
          placeholder="전화번호"
          value={this.state.phone}
          onChange={this.handleChange}
          name="phone"
        />
        <button type="submit">등록</button>
      </form>
    );
  }
}

export default PhoneForm;

PhoneInfoList.js

import React, { Component } from 'react';

class PhoneForm extends Component {
  state = {
    name: '',
    phone: '' //state에 name속성이 있어야 state.name, state.phone으로 불러올 수 있음.
  }
  handleChange = (e) => {
    this.setState({
        [e.target.name]: e.target.value //여기서 name은 name속성을 말하는 것인데, 
        //배열로 감싼 이유는 여러개 를 e.target.value로 넣어주려고 그런듯
    })
  }
  handleSubmit = (e) => {
    // 페이지 리로딩 방지 (원래 form에서 submit이 발생하면 페이지 리로딩이되는데, 
    // 그러면 우리가 지니고있는 상태값을 다 잃어버리므로 방지시킴)
    e.preventDefault(); //원래 이벤트가 해야하는 작업 방지
    
    // 상태값을 onCreate 를 통하여 부모에게 전달 (props로 애초에 부모인 App.js에서 
    // onCreate함수가 정의되어있는데, 그 함수를 그냥 쓴거다. 자식에서 그러니까
    // 사실은 여기서 부모에게 전달해준다고 이해한다기 보다는 , 부모에서 PhoneForm에다가 
    // onCreate함수를 써놨기 때문에 상태값을 전달해줄 수밖에 없는 것이다.)
    this.props.onCreate(this.state);
    // 상태 초기화
    this.setState({
      name: '',
      phone: ''
    })
  }
  render() {
    return (
        // onSubmit을 안써주면 말짱도루묵ㅋㅋ
      <form onSubmit={this.handleSubmit}>
        <input
          placeholder="이름"
          value={this.state.name}
          onChange={this.handleChange}
          name="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 {
  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></div>
        <div>{phone}</div>
      </div>
    );
  }
}

export default PhoneInfo;

결과화면


App.js에서

state = {
    information: [
      {
        id: 0,
        name: '김민준',
        phone: '010-0000-0000'
      },
      {
        id: 1,
        name: '홍길동',
        phone: '010-0000-0001'
      }
    ]
  }
  handleCreate = (data) => {
    const { information } = this.state; //state가 김민준,홍길동 있는 배열임
    this.setState({
      information: information.concat({ id: this.id++, ...data })
    }) //information에 이어서 id는 id값에 +1하는거고, data는 form으로 들어온 값
  }

그리고 PhoneInfoList에 data는 김민준, 홍길동 , 그리고 form으로 들어온 값 전체가 information이 되기 때문에 그게 list로 보여질 것이다.

다시 말해서,

information: information.concat({ id: this.id++, ...data })

이 코드를 해설하자면,
새로운 정보가 form에 입력되어 전송되면
information에 이어 붙이는 것이다. id랑 들어온 data 모두

즉, id : this.id++ 
name : 사용자가 입력한 name
phone : 사용자가 입력한 phone 이 state.information에 저장된다.

그렇다면

<PhoneInfoList data={this.state.information}/>

이 코드에서 this.state.information은
PhoneForm에서 input으로 사용자에게 받은 name, phone, 그리고 자동으로 생성되는 id 값이
원래 있었던 홍길동, 김민준 껏과 합쳐진 것이 되겠다.
이것을 data에 담아서 호출하면

//PhoneInfoList.js
  render() {
    const { data } = this.props;
    const list = data.map( 
      info => (<PhoneInfo key={info.id} info={info}/>) //이 info가 저 info인지 어케알지,,,,?? 
      // => data를 하나씩 쪼갠걸 info로 불러가지구,,,,
      //data가 props로 받은걸 data로 하는데 그 데이터 덩어리를 하나씩 쪼갠게 info고,,,그 info를 info로 넣겠다...?
    );

위 코드의 주석과 같은 역할을 한다.

그럼 PhoneInfo컴포넌트가 호출되엇기 때문에

//PhoneInfo.js
const {
      name, phone, id
    } = this.props.info;
    
    return (
      <div style={style}>
        <div><b>{name}</b></div>
        <div>{phone}</div>
      </div>
    );

props로 info를 받아와서, name, phone 으로 상수 선언 해두엇으니
{name}, {phone}으로 꺼내 쓰는 것이다.

출처

누구든지 하는 리액트 7편 -벨로퍼트님

profile
기록이 쌓이면 지식이 된다.

0개의 댓글